在WPF中,将数据绑定到当前DataContext/Source属性的父级/同级。

6
我们如何绑定到当前数据上下文的父级/兄弟节点(即代表当前数据上下文的源属性)?我不是在谈论绑定到父控件的属性(这种情况涉及目标的父项而不是源的父项),可以通过使用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>

那么{Binding DataContext.Departments, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}}不是你想要的吗? - Markus Hütter
嗯...没想到我可以使用父控件的DataContext属性来获取父数据项.. :)。 - publicgk
为了方便起见,我将我的评论作为答案添加了进来 =) - Markus Hütter
3个回答

12

你可以像这样访问祖先 DataContext:

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

这是标准和推荐的方式吗?看起来比其他方法更容易(修改源属性)。 - publicgk
在我的情况下,我正在使用Telerik RadGridView,因此我需要在上述解决方案中将DataGrid更改为telerik:RadGridView。 - muhammad kashif

3

在大多数情况下,我使用 DataContext 作为路径的根:

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

0

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

1)给每个人一个要绑定到的部门列表。在您的示例中,您可以在Person构造函数中传递列表。或者,给每个人一个返回父级的引用,以便访问父级的任何属性,如:{Binding Parent.Departments}

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

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

然后您可以在树的任何较低位置绑定它:

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接