2010-04-20 137 views
17

当我尝试将窗口的高度和宽度绑定到视图模型中的属性时,出现一些问题。这里有一个小例子来说明问题。这是app.xaml.xs与窗口高度和宽度绑定的问题

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

这是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> 

这是视图模型:

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

当节目的开始WindowHeight和WindowBorderThickness(但不是WindowWidth)的getter被调用,所以窗口的高度和边界被正确设置,但不是宽度。

我再添加按钮,将触发的PropertyChanged所有属性,使视图模型现在看起来是这样的:

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

现在,当我按一下按钮,WindowBorderThickness的吸叫,但不WindowWidth和WindowHeight。这一切似乎很奇怪,对我来说不一致。我错过了什么?

+1

您在调试时在输出窗口中有任何警告吗? – Drake 2010-04-20 13:59:02

+0

不,没有警告。 – 2010-04-20 14:12:42

回答

8

我会尽量回答我自己的问题。绑定正在工作,但我们不能确定布局系统是否要求窗口的Width属性。

MSDN

如果该元素是一些其他的元素中的子元素,然后设置该属性的值是真的只是一个建议值。布局系统以及父元素的特定布局逻辑将在布局过程中将该值用作非绑定输入。实际上,FrameworkElement几乎总是别的东西的子元素;即使您在窗口上设置高度。 (有关的窗口,则当底层应用模型确立了在承载应用的HWND基本渲染假设使用该值。)

,似乎工作的溶液到WINDOWWIDTH属性绑定为minWidth和MaxWidth ,以及宽度。至少在我上面使用的测试场景中,其中一个将被检索。

-1

我不认为你可以动态设置窗口大小

0

我不确定你的具体实现,但我只写了一个可能有用的例子。

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> 

代码

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#代码

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

这里的基本区别是,当我绑定到一个单独的视图模型时,你绑定到MainWindow本身。这似乎有所作为,出于某种原因。如果我对你的视图模型实现你的滑块,它将不起作用(除非我也像我在自己的答案中所述那样绑定到MinHeight和MaxHeight)。无论如何感谢这个例子。 – 2010-04-20 13:17:21

1

绑定为minWidth和了minHeight是正确的。此外,如果您需要绑定到MaxWidth和MaxHeight,如果您的动态将会放大或缩小Window的大小。

4

此外,您可以使用SizeToContent="WidthAndHeight"MinHeightMinWidth,所以没有多余的调用将需要为MaxHeightMaxWidth

9

我有同样的问题,我注意到它取决于是否先写入xaml的高度或宽度。如果高度是第一个,那么绑定仅适用于它,反之亦然。解决的办法是设置结合模式为“双向”: 我做了该项目与2010年MS Studio和.NET 4.0

27

尝试使用双向绑定,它为我工作:

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

好的,

我有同样的问题,无法正确绑定到我的viewmodel通过XAML的窗口尺寸(最小,最大,正常)。

我不知道为什么,但如果您通过代码而不是通过XAML来完成所有这些绑定,那么您可以毫无问题地实现这些绑定。

这里是我的C#代码工作:

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

奇怪的是,它只能在代码,而不是在XAML。更奇怪的是,它默认绑定TwoWay的mMin和Max尺寸,但不是用于您必须指定«Mode = BindingMode.TwoWay»的Normal尺寸。

应该有一个错误,微软必须纠正这一点...