【问题标题】:How to access parent's DataContext from a UserControl如何从 UserControl 访问父级的 DataContext
【发布时间】:2011-07-04 19:00:49
【问题描述】:

我需要从我在 WPF 中创建的 UserControl(包含文本框和列表框的网格:我需要在此列表框中插入项目)访问容器的 DataContext:这是最好的方法吗?

我正在考虑将 DataContext 作为参数传递给用户控件,但认为有一种更简洁的方法。

【问题讨论】:

    标签: wpf user-controls datacontext


    【解决方案1】:

    通常DataContext 将是inherited,只是不要在UserControl 上显式设置它,它会从其父级获取它。如果您必须设置它,您仍然可以使用Parent 属性来获取父级,然后您可以将其安全地转换为FrameworkElement,如果它不为空,您可以获取它的DataContext

    【讨论】:

    • 如果目标控件嵌套在一个或多个其他控件中,则目标控件的父控件可能会更改 DataContext,因此您可能看不到目标控件中的预期对象。 IMO,应该有一堆 DataContexts 可以访问。
    • @Todd:嗯,你可以写一个方法,让它走上树并获得所有唯一的DataContexts,我想我以前可能做过类似的事情。
    【解决方案2】:

    有时我有嵌套的用户控件,而孙子用户控件有时需要祖父视图的数据上下文。到目前为止,我发现的最简单的方法(而且我有点新手)是使用以下方法:

    <Shared:GranchildControl DataContext="{Binding RelativeSource={RelativeSource 
                        FindAncestor, AncestorType={x:Type GrandparentView}},
                        Path=DataContext.GrandparentViewModel}" />
    

    如果您想了解更多详情,我在我的博客上写了more detailed example

    【讨论】:

      【解决方案3】:

      将此 BindingProxy 类添加到您的项目中:

      using System.Windows;
      
      namespace YourNameSpace
      {
          /// <summary>
          /// Add Proxy <ut:BindingProxy x:Key="Proxy" Data="{Binding}" /> to Resources
          /// Bind like <Element Property="{Binding Data.MyValue, Source={StaticResource Proxy}}" />   
          /// </summary>
          public class BindingProxy : Freezable
          {
              protected override Freezable CreateInstanceCore()
              {
                  return new BindingProxy();
              }
      
              public object Data
              {
                  get { return (object)GetValue(DataProperty); }
                  set { SetValue(DataProperty, value); }
              }
      
              public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy));
          }
      }
      
      1. 将 BindingProxy 添加到 UserControl 的资源中。
      2. 将 BindingProxy 的“数据”属性设置为您需要的任何值,例如搜索父窗口。 Data="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext}" 如果您需要更复杂的东西,您可以使用自定义转换器。

      现在您可以访问该父级的 DataContext:{Binding Data.MyCommand, Source={StaticResource BindingProxy}}

      <UserControl 
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
               xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
               xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
               xmlns:common="clr-namespace:YourNameSpace;assembly=YourAssembly"
               mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300">
          <UserControl.Resources>
              <common:BindingProxy x:Key="BindingProxy" Data="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext}" />
          </UserControl.Resources>
          <Border>
              <Button Command="{Binding Data.MyCommand, Source={StaticResource BindingProxy}}">Execute My Command</Button>
              <!-- some visual stuff -->
          </Border>
      </UserControl>
      

      【讨论】:

      • 这里最好的优雅解决方案!
      • 很好的解决方案。
      【解决方案4】:

      H.B.回答标题中的问题。

      但是,文本提出了不同的设计问题。我会请你重新考虑你的设计。

      只要中间没有人显式覆盖,控件就会继承其祖先的 DataContext 属性。
      如果用户控件需要数据,它应该从其数据源(用户控件的视图模型)中获取数据。因此在这种情况下,用户控件可以从SomeViewModel 实例上公开的ListItemsForDisplay 属性中获取所需的数据。无需让父母和演员..更清洁。

      <ContainerType DataSource={Binding SomeViewModel}>
        <YourUserControl>
          <ListBox ItemsSource={Binding ListItemsForDisplay}"/>
      ...
      

      【讨论】:

        【解决方案5】:

        在这种情况下,UserControl 将获得 DataContext 窗口

        <Window>
            <local:MyUserControl DataContext="{Binding}"/>
        </Window>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-12-21
          • 1970-01-01
          • 2010-12-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多