Question

Je dois savoir comment communiquer entre ViewModels. Je suis nouveau sur MVVM alors soyez gentil.

Voici un exemple muet

Définitions de classe (supposons que j'ai associé l'événement 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");
        }
    }
}

Voici ce que vous voyez dans le dictionnaire de ressources

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

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

et le code-behind de ChildView:

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

Le problème évident est que lorsque ChildView est instancié (via la sélection à partir du DataTemplate), il crée une nouvelle classe ChildViewModel et le ParentViewModel n'y a pas accès.

Alors, comment puis-je instancier le DataContext de la Vue comme étant le ViewModel d'origine qui a entraîné la sélection de DataTemplate?

Une solution évidente consiste à modifier les propriétés du ChildViewModel dans le ParentViewModel, mais je préférerais les séparer, car elles peuvent être réutilisées.

Je suis sûr que la réponse est triviale, je voudrais juste savoir ce que c'est. :)

Merci d'avance.

Était-ce utile?

La solution

Vous devez simplement supprimer la ligne:

DataContext = new ChildViewModel();

Le DataContext de la vue sera défini automatiquement par WPF. DataTemplates a toujours son contexte de données défini sur les données du modèle (dans ce cas, le ViewModel):

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

Le résultat final est que vous pouvez créer vos objets de modèle de vue séparément (classes parent et enfant), puis les afficher ultérieurement en les branchant simplement dans des contrôles de contenu.

Autres conseils

Le moyen le plus simple de communiquer entre ViewModels à l'aide de l'approche MVVM consiste à utiliser le modèle Mediator (EventAggregator dans Prism). Vous trouverez un bon exemple de cette approche dans les liens suivants:

  1. modèle MVVM Mediator de Sacha Barber
  2. MVVM + Médiateur de Marlon Grech

Consultez également le MVVM exemple du framework de projet.

Supposons que vous ayez un QueueView qui utilise un 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");
        }
    }
}

- Partie 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>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top