Вопрос об архитектуре привязки данных WPF - PullRequest
5 голосов
/ 30 апреля 2011

Я пытаюсь научиться использовать привязку WPF и архитектуру MVVM.Я сталкиваюсь с некоторыми проблемами со свойствами зависимости.Я пытался контролировать видимость элемента в представлении, привязав его к DependencyProperty в DataContext, но он не работает.Независимо от того, что я установил значение 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 ]

2 голосов
/ 30 апреля 2011

Снимите ElementName с вашей привязки, это не кажется правильным. Измените его на:

<Grid x:Name="_myGrid"
        Visibility="{Binding Path=GridVisible,
            Converter={StaticResource BoolToVisConverter}}">
1 голос
/ 30 апреля 2011

Пусть ваш ViewModel реализует INotifyPropertyChanged, а не наследует от DependencyObject. Реализуйте интерфейс и вызовите 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));
        }
    }
0 голосов
/ 30 апреля 2011

Смысл установки ViewModel в качестве DataContext состоит в том, чтобы разрешить легкие относительные привязки, все привязки, в которых вы указываете только Path, принимают DataContext в качестве источника, который наследуется по всему UserControl (если не установлено иное, например, вшаблонные элементы ItemsControl)

Таким образом, когда DataContext установлен в UserControl, вы обычно не указываете источник при привязке к ВМ.(Источниками являются ElementName, RelativeSource и Source)

Кроме того, я лично не буду делать ViewModels наследованными от DependencyObject, так как это вводит сходство с потоками, также точка DependencyProperties делает разреженные структуры данныхболее эффективный, не создавая ненужные поля во всех них (ViewModels обычно является противоположностью разреженным).

...