Вопрос

Мне нужно выяснить, как общаться между ViewModels. Я новичок в MVVM, поэтому будьте добры.

Вот глупый пример

определения классов (предположим, что я перехватил событие Child.PropertyChanged в ParentViewModel):

public class ParentViewModel : ViewModelBase
{
    public ChildViewModel Child { get; set; }
}

public class ChildViewModel : ViewModelBase
{
    String _FirstName;
    public String FirstName 
    {
        get { return _FirstName; }
        set
        {
            _FirstName = value;
            OnPropertyChanged("FirstName");
        }
    }
}

Вот что вы видите в словаре ресурсов

<DataTemplate DataType="{x:Type vm:ParentViewModel}">
    <vw:ParentView/>
</DataTemplate>

<DataTemplate DataType="{x:Type vm:ChildViewModel}">
    <vw:ChildView/>
</DataTemplate>

и программный код ChildView:

public partial class ChildView : UserControl
{
    public QueueView()
    {
        InitializeComponent();
        DataContext = new ChildViewModel();
    }
}

Очевидная проблема заключается в том, что, когда экземпляр ChildView создается (посредством выбора из DataTemplate), он создает новый класс ChildViewModel, а ParentViewModel не имеет к нему доступа.

Итак, как мне создать экземпляр DataContext для View, чтобы он был исходным ViewModel, который привел к выбору DataTemplate?

Очевидным решением проблемы является объединение свойств в ChildViewModel с ParentViewModel, но я бы предпочел разделить его, потому что для повторного использования.

Я уверен, что ответ тривиален, я просто хотел бы знать, что это такое. :)

Заранее спасибо.

Это было полезно?

Решение

Вы должны просто удалить строку:

DataContext = new ChildViewModel();

DataContext представления будет автоматически установлен WPF. Для DataTemplates всегда устанавливается контекст данных, равный данным для шаблона (в данном случае ViewModel):

<DataTemplate DataType="{x:Type vm:ChildViewModel}">
    <vw:ChildView/>
</DataTemplate>

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

Другие советы

Самый простой способ связи между ViewModels с использованием подхода MVVM - это использование шаблона Mediator (EventAggregator в Prism). Хороший пример такого подхода можно увидеть по следующим ссылкам:

<Ол>
  • Шаблон посредника MVVM от Саши Барбера
  • MVVM + Посредник Марлона Греча
  • Также посмотрите MVVM образец основы проекта.

    Допустим, у вас есть QueueView, который использует QueueViewModel.

    public class QueueViewModel : INotifyPropertyChanged
    {
        public ParentType Parent { get; set; }
    
        public QueueViewModel(ParentType parent)
        {
            this.Parent = parent;
            foreach (ChildType child in Parent)
            {
                child.PropertyChanged += delegate(object sender,
                    PropertyChangedEventArgs e)
                {
                    if (e.PropertyName != "IsSelected")
                        return;
    
                    //do something like this:
                    Parent.IsSelected = AllChildrenAreSelected();
                };
            }
        }
    
    }
    
    public class ParentType : INotifyPropertyChanged
    {
        private bool _isSelected;
    
        public IList<ChildType> Children { get; set; }
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                _isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }
    }
    
    public class ChildType : INotifyPropertyChanged
    {
        private string _name;
        private bool _isSelected;
    
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
    
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                _isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }
    }
    

    - часть QueueView

    <StackPanel>
    <CheckBlock Text="{Binding Path=Parent.Name}" 
                IsChecked="{Binding Parent.IsSelected}"/>
    <ItemsControl ItemsSource="{Binding Path=Parent.Children}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>                                    
                <CheckBox Content="{Binding Path=Name}"
                          IsChecked="{Binding Path=IsSelected, Mode=TwoWay}"/>
            </DataTemplate>
        <ItemsControl.ItemTemplate>
    </ItemsControl>
    </StackPanel>
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top