如何从UserControl访问父级的DataContext

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从UserControl访问父级的DataContext相关的知识,希望对你有一定的参考价值。

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

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

答案

通常DataContext将是inherited,只是不明确地将它设置在UserControl上,它将从它的父母那里得到它。如果你必须设置它,你仍然可以使用Parent属性来获取父级,然后你可以安全地转换为FrameworkElement,如果它不是null,你可以抓住它的DataContext

另一答案

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

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

如果你想要更多细节,我在我的博客上写了一个more detailed example

另一答案

将此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'属性设置为您需要的任何属性,例如搜索父窗口。 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>
另一答案

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

然而,该文本提出了不同的设计问题。我请你重新考虑你的设计。

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

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

以上是关于如何从UserControl访问父级的DataContext的主要内容,如果未能解决你的问题,请参考以下文章

从嵌套类的函数访问父级的非静态成员

如何在 Angular 11 中访问两个父级的路由参数?

如何有效地通过 React 中父级的引用访问子级?

访问父级的受保护变量

如何从嵌套的对象数组中获取每个父级的值

如何从父级及其子级的 Firebase 中获取随机数据 [重复]