web-dev-qa-db-fra.com

Utilisation du DataContext du parent (WPF - Dynamic Menu Command Binding)

J'ai parcouru ce site Web et Google et les solutions n'ont pas fonctionné pour moi.

J'ai une commande sur le ViewModel d'un UserControl. Eh bien, l'usercontrol a un ItemsControl lié à un ObservableCollection. A l'intérieur du DataTemplate du ItemsControl.ItemTemplate J'ai un bouton et je veux utiliser la commande. Je ne peux pas lier la commande car à l'intérieur du DataTemplate, le datacontext n'est pas le ViewModel mais un élément de l'ObservableCollection.

La question est: comment puis-je lier le bouton à la commande en cas de perte du contexte de données parent?

Je pense que cela doit avoir une solution facile parce que je pense que c'est un problème commun.

Imaginez ce scénario:

Vous avez un élément ListBox avec une observableCollection comme ItemsSource, vous utilisez donc un modèle de données à l'intérieur du ListBox pour chaque élément de la collection. Eh bien, vous voulez supprimer l'élément sélectionné et vous mettez un bouton dans chaque ligne pour ce travail. Comment tu fais ça?

Dans MVP, je peux le faire dans l'événement click du bouton:

Button but = e.Source as Button;

if (but != null)
      Presenter.ActualNote = but.DataContext as Note;

En bref. Vous envoyez le contexte de données de la ligne (l'élément sélectionné) au présentateur.

Mais, comment puis-je le faire de la manière mvvm? Parce que je dois utiliser une commande mais je ne peux pas assigner la commande au bouton car le bouton ne sait rien du ViewModel (où la commande existe).

Comme vous pouvez le voir, le bouton doit exister à l'intérieur du modèle de données, puis le datacontext n'est plus le ViewModel .... C'est pourquoi j'ai besoin d'accéder au DataContext du parent, pour accéder à la commande.

J'espère que vous comprenez mieux mon problème.

Je vous remercie.

30
Jesus Rodriguez

Si vous voulez une solution sale qui brise MVVM, définissez le Tag = "{Binding}" sur le bouton et gérez l'événement Click. Dans le gestionnaire d'événements, appelez la commande sur votre ViewModel.

5
geofftnz

Utilisez la liaison ci-dessous pour la commande de votre bouton:

{Binding DataContext.CommandName, 
         RelativeSource={RelativeSource FindAncestor, 
                         AncestorType={x:Type MyUserControl}}}

Cela lui dira de trouver votre UserControl et d'utiliser son DataContext.

89
Eddie Deyo

Alors, qu'en est-il de la modification de votre classe d'élément de données afin qu'elle ait une propriété faisant référence à la vue de modèle entière?

Si votre ItemsSource est de type ObservableCollection<DataItem> puis modifiez le type DataItem comme ceci:

public class DataItem
{
    public BusinessObject Value { get; set; }

    private ModelView modelView;

    public ModelView ModelView
    {
        get
        {
            return modelView;
        }
    }

    public DataItem(ModelView modelView)
    {
        this.modelView = modelView;
    }
}
3
Dmitry Tashkinov

RelativeSource fonctionne, mais je ne pense pas qu'il soit juste de laisser les contrôles rôder dans les propriétés des autres. Il est étrange que le bouton placé à l'intérieur d'une vue d'élément fasse quelque chose avec une source de données externe plutôt qu'avec l'élément lié. Vous devrez peut-être revoir la conception du code du programme.

2
Dmitry Tashkinov