2010-06-10 2 views
6

Этот пример, по общему признанию, немного надуманный, но я делаю что-то подобное. Скажем, у меня есть следующие простые классы:Есть ли простой способ указать привязку данных WPF, где путь один «уровень» вверх?

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

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

И давайте говорить, что у меня есть Xaml с LayoutRoot сеткой и DataGrid, где я хочу, чтобы получить доступ к свойству Имени в DataGrid вместо свойств Альтернативных имен, как во второй колонке здесь:

<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> 

это интуитивно, как бы я пытаться связать имя, но само собой разумеется, что выглядит глупо. Есть ли что-то подобное при указании пути, или вы вынуждены получать относительный источник до контекста данных LayoutRoot. Если вам нужно, каков наиболее эффективный способ?

+0

Почему это не работает? 'Binding =" {Binding Name, Mode = TwoWay} "' – Amsakanna

+0

@Veer, потому что в классе Alias ​​нет свойства Name ... – Anvaka

+0

@Anvaka: Но в datacontext задан экземпляр класса person. Он должен знать свойство Name. – Amsakanna

ответ

10

Это должно работать для вас:

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

Вы можете использовать любой из следующих действий:

Для того, чтобы исходный элемент равен ближайшего родителя данного типа:

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

Чтобы сделать исходный элемент равным n-му ближайшему родительскому элементу данного типа:

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

Для того, чтобы исходный элемент равен предыдущий элемент данных в сборе данных с привязкой:

{Binding RelativeSource={RelativeSource PreviousData}} 
+1

Это возмутительно многословие. Ваш первый пример должен быть написан '{Binding RelativeSource = {RelativeSource FindAncestor, Grid, 3}}'. Другие должны быть упрощены. Любой, кто понимает функцию FindAncestor, будет понимать «FindAncestor, Grid, 3» так же легко, как и ваши четыре строки кода, и с меньшим мышлением. –

0

Я думаю, что нет лучшего способа сделать это, чем при использовании относительного источника до дерева. Вы можете переписать свою модель (например, добавить ссылку на родителя Person от Alias), но это вряд ли лучший подход.

С точки зрения производительности я никогда не встречал узкие места в относительных связываниях источника. Всегда есть что-то еще, что отвлекает ваше приложение от скорости ракеты.