【问题标题】:Bind to a parent/sibling of current datacontext/source property in WPF绑定到 WPF 中当前数据上下文/源属性的父级/兄弟级
【发布时间】:2011-08-11 12:15:39
【问题描述】:

我们如何绑定到当前数据上下文的父/兄弟(即表示当前数据上下文的源属性)?

我不是在谈论绑定到父控件的属性(这种情况涉及目标的父级而不是源的父级) - 这可以通过使用 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}}} 不是你想要的?
  • hmmm...没想到我可以使用父控件的DataContext属性来获取父数据项.. :).
  • 为了您的方便添加了我的评论作为答案 =)

标签: wpf data-binding


【解决方案1】:

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

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

【讨论】:

  • 这是标准和推荐的方式吗?似乎比其他方法更容易(修改源属性)。
  • 在我的情况下,我使用的是 Telerik RadGridView,因此我需要在上述解决方案中使用 Telerik:RadGridView 更改 DataGrid。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2013-01-20
      • 1970-01-01
      • 1970-01-01
      • 2016-06-13
      • 1970-01-01
      • 1970-01-01
      • 2013-02-02
      • 1970-01-01
      • 2022-07-10
      相关资源
      最近更新 更多