Pergunta

Eu preciso descobrir como se comunicar entre ViewModels. Eu sou novo para MVVM então por favor seja gentil.

Aqui está uma idiotizadas exemplo

definições de classe (supor que eu tenha ligado o evento Child.PropertyChanged na 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");
        }
    }
}

Aqui está o que você vê no recurso dicionário

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

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

eo código-behind do ChildView:

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

O problema óbvio é que quando o ChildView é instanciado (via seleção do DataTemplate) ele cria uma nova classe ChildViewModel e não o ParentViewModel não tem acesso a ele.

Então, como posso instanciar o DataContext do Vista para ser o ViewModel original que causou o DataTemplate para ser selecionado?

Uma correção óbvia é mmerge as propriedades na ChildViewModel no ParentViewModel, mas eu preferia separá-lo porque para reutilização.

Eu tenho certeza que a resposta é trivial, eu só gostaria de saber o que é. :)

Agradecemos antecipadamente.

Foi útil?

Solução

Você deve simplesmente remover a linha:

DataContext = new ChildViewModel();

O DataContext da exibição será definido automaticamente pelo WPF. DataTemplates sempre tem o seu conjunto de contexto de dados para os dados para o modelo (neste caso, o ViewModel):

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

O resultado final é que você pode construir seu modelo de exibição objetos separadamente (ambas as classes pai e filho) e depois exibi-los mais tarde, basta conectá-los em controles de conteúdo.

Outras dicas

A maneira mais fácil de se comunicar entre ViewModels usando a abordagem MVVM é usar o Mediator (EventAggregator em Prism). Um bom exemplo desta abordagem pode ser visto nos seguintes links:

  1. MVVM Mediador Pattern por Sacha Barber
  2. MVVM + mediador por Marlon Grech

Além disso, verifique o MVVM quadro projeto amostra.

Vamos dizer que você tem uma QueueView que usa um 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 parte

<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>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top