2010-06-10 8 views
6

Cet exemple est certes un peu artificiel mais je fais quelque chose de similaire. Disons que j'ai les classes simples suivantes:Existe-t-il un moyen simple de spécifier une liaison de données WPF où le chemin est à un niveau supérieur?

public class Person 
{ 
    public string Name { get; set; } 
    public List<Alias> Aliases { get; set; } 
} 

public class Alias 
{ 
    public string AliasName { get; set; } 
} 

Et disons que je Xaml avec une grille de LayoutRoot, et un DataGrid où je veux accéder à la propriété Name dans le DataGrid au lieu des propriétés alias comme dans la deuxième colonne ici:

<Grid x:Name="LayoutRoot" DataContext="PersonInstance"> 
    <DataGrid ItemsSource="{Binding Aliases}"> 
     <DataGrid.Columns> 
      <data:DataGridTextColumn Header="AliasName" Binding="{Binding AliasName, Mode=TwoWay}"/> 
      <data:DataGridTextColumn Header="Name" Binding="{Binding ../Name, Mode=TwoWay}"/> 
     </DataGrid.Columns> 
    </DataGrid> 
</Grid> 

qui est intuitivement comment je tenterais de lier le nom, mais inutile de dire que l'air stupide. Existe-t-il quelque chose comme cela lorsque vous spécifiez un chemin, ou êtes-vous forcé d'obtenir une source relative jusqu'au contexte de données LayoutRoot? Si vous devez le faire, quel est le moyen le plus efficace?

+0

Pourquoi cela ne fonctionne-t-il pas? 'Binding =" {Binding Name, Mode = TwoWay} "' – Amsakanna

+0

@Veer, car il n'y a pas de propriété Name dans la classe Alias ​​... – Anvaka

+0

@Anvaka: Mais le datacontext est l'instance de la classe person. Il devrait connaître la propriété Name. – Amsakanna

Répondre

10

Cela devrait fonctionner pour vous:

<DataGridTextColumn Header="Name" 
        Binding="{Binding RelativeSource={RelativeSource 
                 FindAncestor, 
                 AncestorLevel=3, 
                 AncestorType={x:Type Grid}, 
                 Mode=FindAncestor}, 
                Path=DataContext.Name}"/> 

Vous pouvez utiliser une des opérations suivantes:

Pour l'élément source égale le parent le plus proche d'un type donné:

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type 
desiredType}}} 

Pour rendre l'élément source égal au nième parent le plus proche d'un type donné:

{Binding RelativeSource={RelativeSource FindAncestor, 
AncestorLevel=n, AncestorType={x:Type desiredType}}} 

Pour rendre l'élément source égale à l'élément de données précédent dans une collection lié aux données:

{Binding RelativeSource={RelativeSource PreviousData}} 
+1

Ceci est outrageusement verbeux. Votre premier exemple devrait être écrit '{Reliant RelativeSource = {RelativeSource FindAncestor, Grid, 3}}'. Les autres devraient également être simplifiés. Quiconque comprend la fonction de FindAncestor comprend 'FindAncestor, Grid, 3' aussi facilement que vos quatre lignes de code, et avec moins de réflexion. –

0

Je pense qu'il n'y a pas de meilleure façon de le faire que d'utiliser source par rapport l'arbre. Vous pouvez réécrire votre modèle (par exemple, ajouter une référence au parent Person de Alias) mais ce n'est guère mieux. Du point de vue de la performance, je n'ai jamais trouvé de goulots d'étranglement dans les liaisons source relatives. Il y a toujours quelque chose d'autre qui maintient votre application loin de la vitesse de fusée.