Как получить доступ к DataContext родителя из UserControl - PullRequest
11 голосов
/ 04 июля 2011

Мне нужно получить доступ к DataContext контейнера из UserControl (сетка, содержащая текстовые поля и список: мне нужно вставить элементы в этот список), который я создал в WPF: какой лучший способ сделать это?

Я думал передать DataContext в качестве параметра пользовательскому элементу управления, но думаю, что есть более чистый способ сделать это.

Ответы [ 4 ]

11 голосов
/ 04 июля 2011

Обычно DataContext будет наследоваться , просто не устанавливайте его явно на UserControl, и он получит его от своего родителя.Если вам нужно установить его, вы все равно можете использовать свойство Parent, чтобы получить родителя, который затем вы можете безопасно привести к FrameworkElement, а если оно не равно нулю, вы можете получить его * 1009.*.

7 голосов
/ 27 октября 2011

У меня иногда есть вложенные пользовательские элементы управления, а пользовательскому контролю внука иногда требуется контекст данных представления бабушки и дедушки. Самый простой способ, который я нашел до сих пор (и я в некоторой степени новичок), заключается в использовании следующего:

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

Я написал более подробный пример в своем блоге, если вы хотите больше подробностей.

2 голосов
/ 27 августа 2016

Добавьте этот класс 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>
1 голос
/ 05 июля 2011

HB отвечает на вопрос в вашем заголовке.

Однако текст ставит другой вопрос о дизайне.Я бы попросил вас пересмотреть свой дизайн.

Элемент управления наследует свойство DataContext своего предка, пока никто между ними явно не переопределяет.
Если элемент управления пользователя нуждается в данных, он должен получить их отего источник данных (viewmodel для пользовательского элемента управления).Таким образом, в этом случае пользовательский элемент управления может получить необходимые ему данные из свойства ListItemsForDisplay, представленного в экземпляре SomeViewModel.Не нужно становиться родителем и разыгрывать .. намного чище.

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