绑定到WPF中当前datacontext / source属性的父/兄弟

时间:2011-04-23 14:40:17

标签: wpf data-binding

我们如何绑定当前datacontext的父/兄弟(即代表当前datacontext的source属性)?

我不是在谈论绑定到父控件的属性(该情况涉及目标的父节点而不是源节点的父节点) - 这可以通过使用RelativeSourceMode = FindAncestor轻松完成。

RelativeSourceMode = PreviousData提供对数据项的前一个兄弟的绑定的有限支持,但不支持父级或其他兄弟。

虚拟示例:
(假设INPC到位)
如何将ComboBox的ItemsSource绑定到ViewModel的Departments属性?

public class Person
{
    public string Name { get; set; }
    public string Department { get; set; }
}

public class PersonViewModel
{
    public List<Person> Persons { get; set; }
    public List<string> Departments { get; set; }

    public PersonViewModel()
    {
        Departments = new List<string>();
        Departments.Add("Finance");
        Departments.Add("HR");
        Departments.Add("Marketing");
        Departments.Add("Operations");

        Persons = new List<Person>();
        Persons.Add(new Person() { Name = "First", Department = "HR" });
        Persons.Add(new Person() { Name = "Second", Department = "Marketing" });
        Persons.Add(new Person() { Name = "Third", Department = "Marketing" });
    }
}

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="300" Width="300">
    <Grid>
        <DataGrid ItemsSource="{Binding Persons}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Departments???}"
                                      SelectedValue="{Binding Department}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

3 个答案:

答案 0 :(得分:11)

您可以像这样访问祖先的DataContext:

<ComboBox ItemsSource="{Binding DataContext.Departments, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}}"
                                  SelectedValue="{Binding Department}"/>

答案 1 :(得分:3)

在大多数情况下,我使用DataContext作为Path root:

{Binding Path=DataContext.MyProperty,ElementName=MyElement}
{Binding Path=DataContext.MyProperty,RelativeSource={RelativeSource AncestorType=MyAnsectorTypr}

答案 2 :(得分:0)

我不确定为什么RelativeSource方法不起作用。 (我一直这样做,AncestorType=UserControl)但如果这是不可接受的,有两种方法可以想到。

1)给每个人一个要绑定的部门列表。在您的示例中,您可以只在Person构造函数中传递列表。或者,给每个人一个回馈父母的参考,以获得父母的任何财产:{Binding Parent.Departments}

2)创建一个附加属性“ParentDataContext”并将其设置在items控件之外,如下所示:

<Window local:Attached.ParentDataContext="{Binding}" ... >

然后你可以在树的任何地方绑定它:

{Binding Path=(local:Attached.ParentDataContext).Departments, RelativeSource=Self}

附加属性必须继承,因此树中较低的所有内容都是通过将其设置在顶层来设置的。