2010-04-20 7 views
17

Ich habe einige Probleme, wenn ich versuche, die Höhe und Breite eines Fensters an Eigenschaften in meinem Ansichtsmodell zu binden. Hier ist eine kleine Beispiel-App, um das Problem zu veranschaulichen. Dies ist der Code in app.xaml.xsProbleme beim Binden an Fenster Höhe und Breite

public partial class App : Application 
{ 
    protected override void OnStartup(StartupEventArgs e) 
    { 
     base.OnStartup(e); 
     MainWindow mainWindow = new MainWindow(); 
     MainWindowViewModel mainWindowViewModel = new MainWindowViewModel(); 
     mainWindow.DataContext = mainWindowViewModel; 
     mainWindow.Show(); 
    } 
} 

Dies ist MainWindow.xaml:

<Window x:Class="TestApp.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Height="{Binding WindowHeight}" 
     Width="{Binding WindowWidth}" 
     BorderThickness="{Binding WindowBorderThickness}"> 
</Window> 

Und dies ist die Ansicht Modell:

public class MainWindowViewModel 
{ 
    public int WindowWidth { get { return 100; } } 
    public int WindowHeight { get { return 200; } } 
    public int WindowBorderThickness { get { return 8; } } 
} 

Wenn das Programm gestartet wird Getter von WindowHeight und WindowBorderThickness (aber nicht WindowWidth) werden aufgerufen, so dass die Höhe und der Rand des Fensters richtig eingestellt sind, aber nicht die Breite.

ich dann auf die Schaltfläche hinzufügen, die Property für alle Eigenschaften, so dass der View-Modell wie folgt aussieht jetzt auslösen:

public class MainWindowViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    public void TriggerPropertyChanges() 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs("WindowWidth")); 
      PropertyChanged(this, new PropertyChangedEventArgs("WindowHeight")); 
      PropertyChanged(this, new PropertyChangedEventArgs("WindowBorderThickness")); 
     } 

    } 

    public ICommand ButtonCommand { get { return new RelayCommand(delegate { TriggerPropertyChanges(); }); } } 

    public int WindowWidth { get { return 100; } } 
    public int WindowHeight { get { return 200; } } 
    public int WindowBorderThickness { get { return 8; } } 
} 

Nun, wenn ich auf die Schaltfläche klicken, wird der Getter von WindowBorderThickness genannt wird, aber nicht die für WindowWidth und WindowHeight. Alles scheint mir sehr komisch und widersprüchlich zu sein. Was vermisse ich?

+1

Haben Sie eine Warnung im Ausgabefenster während des Debuggens? – Drake

+0

Nein, es gibt keine Warnungen. –

Antwort

8

werde ich versuchen, meine eigene Frage zu beantworten. Die Bindungen funktionieren, aber wir können nicht wirklich sicher sein, dass das Layoutsystem z.B. die Width-Eigenschaft des Fensters.

Von MSDN:

Wenn dieses Element ein Element innerhalb eines anderen Elements Kind ist, dann diese Eigenschaft auf einen Wert ist wirklich nur ein Vorschlagswert. Das Layoutsystem sowie die spezielle Layout-Logik des Elternelements verwenden den Wert als eine nicht bindende Eingabe während des Layoutprozesses. In der Praxis ist ein FrameworkElement fast immer das Kindelement von etwas anderem; selbst wenn Sie die Höhe auf Fenster einstellen. (Für Fenster, wird dieser Wert verwendet, wenn das zugrunde liegende Anwendungsmodell der Grundes Rendering Annahmen fest, dass der Hwnd schaffen, den die Anwendung hostet.)

Eine Lösung, die die Windowwidth-Eigenschaft auf MinWidth und MaxWidth ist zu binden, scheint zu funktionieren sowie Breite. Einer davon wird abgerufen, zumindest in dem Testszenario, das ich oben verwendet habe.

-1

Ich glaube nicht, dass Sie die Fenstergröße

dynamisch einstellen
0

Ich bin mir nicht sicher über Ihre spezifische Implementierung, aber ich schreibe nur ein Beispiel, das vielleicht hilfreich sein könnte.

XAML

<Window x:Name="MainWindow" 
    x:Class="MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" 
    MinWidth="200" 
    MinHeight="100" 
    Width="{Binding ElementName=MainWindow, Path=WindowWidth}" 
    Height="{Binding ElementName=MainWindow, Path=WindowHeight}"> 
    <Grid> 
     <Slider 
      x:Name="slWidth" 
      Value="{Binding ElementName=MainWindow, Path=WindowWidth, Mode=TwoWay}" 
      Minimum="200" 
      Maximum="1600" 
      Height="23" HorizontalAlignment="Left" Margin="56,22,0,0" VerticalAlignment="Top" Width="61" /> 
     <Label 
      Content="Width" 
      Height="28" 
      HorizontalAlignment="Left" 
      Margin="12,22,0,0" 
      Name="Label1" 
      VerticalAlignment="Top" /> 
     <Slider 
      x:Name="slHeight" 
      Value="{Binding ElementName=MainWindow, Path=WindowHeight, Mode=TwoWay}" 
      Minimum="100" 
      Maximum="800" 
      Height="23" HorizontalAlignment="Left" VerticalAlignment="Top" Width="61" Margin="56,51,0,0" /> 
     <Label 
      Content="Height" 
      Height="28" 
      HorizontalAlignment="Left"    
      VerticalAlignment="Top" Margin="12,46,0,0" /> 
    </Grid> 
</Window> 

-Code

Class MainWindow 

    Public Shared ReadOnly WindowWidthProperty As DependencyProperty = _ 
          DependencyProperty.Register("WindowWidth", _ 
          GetType(Integer), GetType(MainWindow), _ 
          New FrameworkPropertyMetadata(Nothing)) 

    Public Shared ReadOnly WindowHeightProperty As DependencyProperty = _ 
         DependencyProperty.Register("WindowHeight", _ 
         GetType(Integer), GetType(MainWindow), _ 
         New FrameworkPropertyMetadata(Nothing)) 

    Public Property WindowWidth As Integer 
     Get 
      Return CInt(GetValue(WindowWidthProperty)) 
     End Get 
     Set(ByVal value As Integer) 
      SetValue(WindowWidthProperty, value) 
     End Set 
    End Property 

    Public Property WindowHeight As Integer 
     Get 
      Return CInt(GetValue(WindowHeightProperty)) 
     End Get 
     Set(ByVal value As Integer) 
      SetValue(WindowHeightProperty, value) 
     End Set 
    End Property 


End Class 

C# -Code

public readonly DependencyProperty WindowWidthProperty = DependencyProperty.Register("WindowWidth", typeof(Double), typeof(MainWindow), new FrameworkPropertyMetadata()); 
public readonly DependencyProperty WindowHeightProperty = DependencyProperty.Register("WindowHeight", typeof(Double), typeof(MainWindow), new FrameworkPropertyMetadata()); 

public double WindowWidth { 
    get { return Convert.ToDouble(this.GetValue(WindowWidthProperty)); } 
    set { this.SetValue(WindowWidthProperty, value); } 
} 

public double WindowHeight { 
    get { return Convert.ToDouble(this.GetValue(WindowHeightProperty)); } 
    set { this.SetValue(WindowHeightProperty, value); } 
} 
+1

Der grundlegende Unterschied besteht darin, dass Sie an das MainWindow selbst gebunden sind, während ich an ein separates Ansichtsmodell gebunden bin. Dies scheint aus irgendeinem Grund einen Unterschied zu machen. Wenn ich meine Schieberegler gegen mein Ansichtsmodell einfüge, funktioniert es nicht (es sei denn, ich bin auch an MinHeight und MaxHeight gebunden, wie ich in meiner eigenen Antwort angegeben habe). Danke für das Beispiel trotzdem. –

1

zu MinWidth und MinHeight Bindung korrekt ist. Wenn Sie eine Bindung an MaxWidth und MaxHeight benötigen, wenn Ihre Dynamik die Größe von Window vergrößert oder verkleinert.

4

Zusätzlich können Sie SizeToContent="WidthAndHeight" mit dem MinHeight und MinWidth, verwenden Sie so keine zusätzlichen Anruf würde erfordern, die für MaxHeight und MaxWidth.

9

Ich hatte das gleiche Problem und habe festgestellt, dass es darauf ankommt, ob Höhe oder Breite zuerst in XAML geschrieben wird. Wenn die Höhe zuerst ist, dann funktioniert die Bindung nur für sie und umgekehrt. Die Lösung Binding-Modus 'TwoWay' gesetzt war: Das Projekt, das ich gemacht habe, war mit MS Studio 2010 und .NET 4.0

27

Versuchen Sie es mit zwei Art und Weise verbindlich, es funktionierte für mich:

Width="{Binding Path=xExt, Mode=TwoWay}" 
1

OK,

Ich hatte das gleiche Problem und konnte die Fensterabmessungen (min, max, normal) zu meinem viewmodel durch XAML nicht richtig binden.

Ich weiß nicht warum, aber Sie können alle diese Bindungen ohne jedes Problem erreichen, wenn Sie sie durch Code statt durch XAML tun.

Hier ist mein C# -Code, die gearbeitet:

this.SetBinding(Window.WidthProperty, new Binding("Width") { Source = MyViewModel, Mode=BindingMode.TwoWay }); 
this.SetBinding(Window.HeightProperty, new Binding("Height") { Source = MyViewModel, Mode=BindingMode.TwoWay }); 
this.SetBinding(Window.MaxWidthProperty, new Binding("MaxWidth") { Source = MyViewModel }); 
this.SetBinding(Window.MaxHeightProperty, new Binding("MaxHeight") { Source = MyViewModel }); 
this.SetBinding(Window.MinWidthProperty, new Binding("MinWidth") { Source = MyViewModel }); 
this.SetBinding(Window.MinHeightProperty, new Binding("MinHeight") { Source = MyViewModel }); 

Es ist seltsam, dass es nur in Code funktioniert und nicht in XAML. Noch merkwürdiger ist es, dass TwoWay standardmäßig für die Dimensionen mMin und Max gebunden wird, nicht aber für die Dimensionen Normal, für die Sie «Mode = BindingMode.TwoWay» angeben müssen.

Es sollte einen Fehler geben, den Microsoft zu diesem Thema korrigieren muss ...