WPF数据绑定架构问题

时间:2011-04-29 21:27:24

标签: c# wpf xaml dependency-properties datacontext

我正在尝试学习如何使用WPF绑定和MVVM架构。我在Dependency Properties遇到了一些麻烦。我试图通过将它绑定到DataContext中的DependencyProperty来控制视图上项目的可见性,但它不起作用。无论我在下面的视图模型的构造函数中设置GridVisible值,它在运行代码时始终显示为可见。

谁能看到我出错的地方?

C#代码(ViewModel):

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>

我在线查看了几个教程,看起来我正确地遵循了我在那里发现的内容。有任何想法吗?谢谢!

3 个答案:

答案 0 :(得分:2)

从你的绑定中取出ElementName,这似乎不正确。 将其更改为:

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

答案 1 :(得分: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));
        }
    }

答案 2 :(得分:0)

将ViewModel设置为DataContext的目的是启用简单的相对绑定,所有绑定只指定Path,将DataContext作为源,在整个UserControl中继承(除非另有设置,例如在ItemsControl的模板化项目中

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

此外,我个人不会让ViewModel继承自DependencyObject,因为这会引入线程亲和性,而且DependencyProperties的一点是通过不在所有这些中创建不必要的字段来使稀疏数据结构更有效(ViewModels通常是相当的)与稀疏相反的。)