2011-04-29 88 views
5

我在学习如何使用WPF绑定和MVVM体系结构。我遇到了依赖属性的一些麻烦。我试图通过将它绑定到DataContext中的DependencyProperty来控制视图上项目的可见性,但它不起作用。无论我如何在下面的视图模型的构造函数中设置GridVisible值,在运行代码时它总是显示为可见。WPF数据绑定体系结构问题

任何人都可以看到我要去哪里错了吗?

C#代码(视图模型):

public class MyViewModel : DependencyObject 
{ 
    public MyViewModel() 
    { 
     GridVisible = false; 
    } 

    public static readonly DependencyProperty GridVisibleProperty = 
    DependencyProperty.Register(
     "GridVisible", 
     typeof(bool), 
     typeof(MyViewModel), 
     new PropertyMetadata(false, 
       new PropertyChangedCallback(GridVisibleChangedCallback))); 

    public bool GridVisible 
    { 
     get { return (bool)GetValue(GridVisibleProperty); } 
     set { SetValue(GridVisibleProperty, value); } 
    } 

    protected static void GridVisibleChangedCallback(
     DependencyObject source, 
     DependencyPropertyChangedEventArgs e) 
    { 
     // Do other stuff in response to the data change. 
    } 
} 

XAML代码(查看):

<UserControl ... > 

    <UserControl.Resources> 
     <BooleanToVisibilityConverter x:Key="BoolToVisConverter" /> 
    </UserControl.Resources> 

    <UserControl.DataContext> 
     <local:MyViewModel x:Name="myViewModel" /> 
    </UserControl.DataContext> 

    <Grid x:Name="_myGrid" 
     Visibility="{Binding Path=GridVisible, 
      ElementName=myViewModel, 
      Converter={StaticResource BoolToVisConverter}}"> 

     <!-- Other elements in here --> 

    </Grid> 

</UserControl> 

我在几个教程在网上看了,似乎像我正确地遵循我在那里找到的内容。有任何想法吗?谢谢!

回答

2

从您的绑定中取出ElementName,看起来不正确。 将其更改为:

<Grid x:Name="_myGrid" 
     Visibility="{Binding Path=GridVisible, 
      Converter={StaticResource BoolToVisConverter}}"> 
+0

其实我把你的代码复制出来,发现它与包含和不包含ElementName的绑定一起工作。你在使用usercontrol(即一个窗口或其他用户控件)?也许在那里有什么问题(你没有包含代码)。 – thornhill 2011-04-29 21:51:28

+0

我删除了ElementName,它仍然不起作用。看起来你是对的 - 它可能与我的代码的另一部分有关,而不是上面发布的消毒版本。不幸的是,我不能发布实际的代码,因为它是为了工作。 – RobotNerd 2011-04-29 21:55:34

+0

在这种情况下,当您运行应用程序并打开包含此用户控件的窗口时,请在VisualStudio的“输出”窗口中查找与此文本类似的任何错误。 “BindingExpression path error:'GridVisible'property not found on 'object ......“ 该消息的内容可能会帮助您进一步调试。 抱歉,我无法帮助你更多。祝你好运。 – thornhill 2011-04-30 08:06:54

0

设置视图模型作为DataContext的的一点是使容易相对绑定,所有绑定在这里你只指定Path采取的DataContext作为源这是整个用户控件继承(除非它是例如在ItemsControl的模板项目中设置)

因此,一旦在UserControl上设置DataContext,通常在绑定到VM时不指定任何源。 (来源是ElementNameRelativeSourceSource

另外我个人不会作出的ViewModels从DependencyObject继承因为这引入线程的亲和性,也DependencyProperties的点是使稀疏数据结构通过不产生在所有的不必要的字段更有效他们(ViewModels通常与稀疏相反)。

+3

'INotifyPropertyChanged'是'DependencyObject'的替代品 - 大多数视图模型使用这种替代依赖项属性。 – 2011-04-29 22:26:23

1

让您的ViewModel实现INotifyPropertyChanged而不是继承DependencyObject。 实现接口并从属性的setter中引发PropertyChanged。

private bool gridVisible; 

    public bool GridVisible 
    { 
     get { return gridVisible; } 
     set 
     { 
      gridVisible = value; 
      OnPropertyChanged("GridVisible"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
+1

您不需要使用ElementName在您的XAML中引用您的虚拟机,也不需要命名虚拟机。将它分配给usercontrol.DataContext时,它将成为用户控件的所有子项的默认绑定源。 – 2011-04-30 08:16:27