2010-04-20 4 views
17

J'ai des problèmes lorsque j'essaie de lier la hauteur et la largeur d'une fenêtre aux propriétés de mon modèle de vue. Voici un petit exemple d'application pour illustrer le problème. Voici le code dans app.xaml.xsProblèmes de liaison avec la hauteur et la largeur de la fenêtre

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(); 
    } 
} 

Ceci est 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> 

Et c'est le modèle de vue:

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

Lorsque le programme est lancé le getters de WindowHeight et WindowBorderThickness (mais pas WindowWidth) sont appelés, donc la hauteur et la bordure de la fenêtre sont définies correctement, mais pas la largeur.

ajouter ensuite le bouton qui déclenchera PropertyChanged pour toutes les propriétés, de sorte que le modèle de vue ressemble maintenant à ceci:

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; } } 
} 

Maintenant, quand je clique sur le bouton, le getter de WindowBorderThickness est appelé, mais pas ceux pour WindowWidth et WindowHeight. Tout semble juste très étrange et inconsistant pour moi. Qu'est-ce que je rate?

+1

Avez-vous un avertissement dans la fenêtre de sortie lors du débogage? – Drake

+0

Non, il n'y a pas d'avertissement. –

Répondre

8

Je vais essayer de répondre à ma propre question. Les liaisons fonctionnent, mais nous ne pouvons pas vraiment être sûrs que le système de disposition demande par ex. la propriété Width de la fenêtre.

De MSDN:

Si cet élément est un élément enfant dans un autre élément, puis définir cette propriété à une valeur est vraiment seulement une valeur suggérée. Le système de mise en page ainsi que la logique de mise en page particulière de l'élément parent utiliseront la valeur comme une entrée non liée pendant le processus de mise en page. En termes pratiques, un FrameworkElement est presque toujours l'élément enfant d'autre chose; même lorsque vous définissez la hauteur sur la fenêtre. (Pour la fenêtre, cette valeur est utilisée lorsque le modèle d'application sous-jacente établit les hypothèses de rendu de base qui créent l'Hwnd qui héberge l'application.)

Une solution qui semble fonctionner est de lier la propriété WindowWidth à MinWidth et MaxWidth , ainsi que la largeur. L'un d'entre eux sera récupéré, au moins dans le scénario de test que j'utilisais ci-dessus.

-1

Je ne pense pas que vous pouvez définir la taille de la fenêtre dynamique

0

Je ne suis pas sûr de votre implémentation spécifique, mais je viens d'écrire un exemple qui pourrait être utile.

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 

code C#

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

La différence fondamentale ici est que vous liez la MainWindow elle-même pendant que je lie à un modèle de vue séparé. Cela semble faire une différence, pour une raison quelconque. Si j'implémente vos curseurs par rapport à mon modèle de vue, cela ne fonctionnera pas (à moins que je ne lie aussi MinHeight et MaxHeight comme je l'ai dit dans ma propre réponse). Merci pour l'exemple quand même. –

1

Reliure à MinWidth et MinHeight est correcte. Aussi, si vous avez besoin de lier à MaxWidth et MaxHeight si votre dynamique va à la fois agrandir ou réduire la taille de la fenêtre.

4

vous pouvez utiliser plus SizeToContent="WidthAndHeight" avec le MinHeight et MinWidth, donc pas appel supplémentaire aurait besoin pour le MaxHeight et MaxWidth.

9

J'ai eu le même problème et j'ai remarqué que cela dépend si la hauteur ou la largeur est écrite en premier dans xaml. Si la hauteur est la première, alors la liaison ne fonctionne que pour elle et vice versa. La solution était de définir le mode de reliure à 'TwoWay': Le projet que j'ai été avec MS Studio 2010 et .NET 4.0

27

Essayez d'utiliser deux voies de liaison, il a travaillé pour moi:

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

OK,

J'ai eu le même problème et n'a pas pu lier correctement les dimensions de la fenêtre (min, max, normal) à mon modèle de vue à travers XAML. Je ne sais pas pourquoi mais vous pouvez réaliser toutes ces liaisons sans problème si vous les faites par code au lieu de XAML.

Voici mon code C# qui a fonctionné:

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 }); 

Il est étrange que cela fonctionne uniquement dans le code et non en XAML. Il est encore plus étrange qu'il lie TwoWay par défaut pour les dimensions mMin et Max mais pas pour les dimensions normales pour lesquelles vous devez spécifier «Mode = BindingMode.TwoWay».

Il devrait y avoir un bogue que Microsoft doit corriger à ce sujet ...

Questions connexes