web-dev-qa-db-fra.com

Liaison WPF au parent DataContext

Nous avons une application WPF avec un modèle MVVM standard, exploitant Cinch (et donc MefedMVVM) pour une résolution de View -> ViewModel. Cela fonctionne bien et je peux lier les contrôles pertinents aux propriétés du ViewModel.

Dans une vue particulière, nous avons un XamGrid Infragistics. Cette grille est liée à une ObservableCollection sur le ViewModel et affiche les lignes appropriées. Cependant, j'ai ensuite une colonne spécifique sur cette grille dans laquelle je tente de lier une valeur de texte TextBox à une propriété du DataContext parent, plutôt qu'à ObservableCollection. Cette liaison échoue.

Nous avons examiné plusieurs options, notamment:

  1. Utiliser AncestorType pour suivre l’arbre et se lier au DataContext du UserControl parent comme suit (de la excellente réponse à cette question, ainsi que celui-ci ) ...

    {Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
    
  2. Spécifier le nom d'élément et essayer de cibler directement le contrôle de niveau supérieur. Avoir un regardez ici si vous souhaitez en savoir plus sur l'utilisation de ElementName.

  3. Utilisation d'un FrameorkElement 'proxy' défini dans les ressources pour que UserControl tente de 'transmettre' le contexte selon les besoins. Nous définissons l'élément comme ci-dessous, puis nous référons en tant que ressource statique ...

    <FrameworkElement x:Key="ProxyContext" DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource Self}}"></FrameworkElement>
    

Dans ce cas, la liaison trouve le FrameworkElement, mais ne peut accéder à rien au-delà de cela (lors de la spécification d'un chemin).

Une fois que vous avez lu, il semble fort probable que cela soit causé par les colonnes de bâtiment Infragistics XamGrid situées en dehors de l’arbre. Toutefois, même si tel est le cas, au moins les options 2 ou 3 devraient fonctionner.

Notre dernière pensée est que cela est lié à la liaison V - VM, mais même en utilisant Snoop, nous n’avons pas encore trouvé le problème exact. Je ne suis en aucun cas un expert avec WPF binding, donc tout pointeur serait apprécié.

EDIT: J'ai trouvé quelques exemples de modèles dans Infragistics ici que je vais essayer.

EDIT 2: Comme l'a souligné @Dtex, les modèles sont la voie à suivre. Voici l'extrait pertinent à utiliser avec un XamGrid:

<ig:GroupColumn Key="CurrentDate">
                <ig:GroupColumn.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Path=DataContext.CurrentDateTest, RelativeSource={RelativeSource AncestorType=UserControl}}" />
                    </DataTemplate>
                </ig:GroupColumn.HeaderTemplate>
                <ig:GroupColumn.Columns>

J'ai laissé le fichier XML ouvert ... vous ajoutez simplement les colonnes que vous voulez, puis fermez les balises correspondantes.

40
Nick

Je ne sais pas à propos de XamGrid mais c'est ce que je vais faire avec un wpf standard DataGrid:

<DataGrid>
    <DataGrid.Columns>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding DataContext.MyProperty, RelativeSource={RelativeSource AncestorType=MyUserControl}}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding DataContext.MyProperty, RelativeSource={RelativeSource AncestorType=MyUserControl}}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

Étant donné que TextBlock et TextBox spécifiés dans les modèles de cellules font partie de l'arborescence visuelle, vous pouvez y accéder et trouver le contrôle dont vous avez besoin.

77
Dtex

En raison de choses comme ceci, en règle générale, j'essaie d'éviter autant que possible les "ruses" de XAML et de garder le XAML aussi bête et simple que possible et de faire le reste dans ViewModel (ou les propriétés attachées ou IValueConverters etc.). si vraiment nécessaire).

Si possible, je donnerais au ViewModel du DataContext actuel une référence (propriété, par exemple) au ViewModel parent correspondant.

public class ThisViewModel : ViewModelBase
{
    TypeOfAncestorViewModel Parent { get; set; }
}

et lier contre cela directement à la place.

<TextBox Text="{Binding Parent}" />

0
bitbonk