Связывание с предками из ResourceDictionary - PullRequest
7 голосов
/ 15 января 2010

Как я могу связать свойство UserControl из его ResourceDictionary? Я хочу, чтобы объект, который я объявил в моих ресурсах, имел тот же DataContext, что и UserControl, в котором он содержится:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Some.Namespace"
    DataContext="{Binding Path=ViewModel, RelativeSource={RelativeSource Self}}">
    <UserControl.Resources>
        <local:SomeClass
            x:Key="SomeClass"
            DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
    </UserControl.Resources>
</UserControl>

Во время выполнения я получаю ошибку:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='UserControl', AncestorLevel='1''. BindingExpression:Path=DataContext; DataItem=null; target element is 'SomeClass' (Name=''); target property is 'DataContext' (type 'Object')

Ответы [ 6 ]

2 голосов
/ 29 сентября 2010

Мой обходной путь - установить DataContext ресурса в коде позади.

.xaml

<local:SomeType x:Key="SomeKey" SomeProperty="{Binding ... }" />

.xaml.cs

public SomeControl()
{
    InitializeComponent();
    ((SomeType)this.Resources["SomeKey"]).DataContext = this;
}
1 голос
/ 14 февраля 2013

Set x: Shared = "False", это клонирует ресурс при каждом использовании и делает его дочерним для вашего элемента, что позволяет использовать привязки.

<local:SomeClass
            x:Key="SomeClass"
            x:Shared="False"
            DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
1 голос
/ 05 февраля 2010

При использовании FindAncestor целевой элемент должен быть потомком (логическим или визуальным) источника.Ваш объект не отображается ни в визуальном, ни в логическом дереве, он просто находится в ресурсах.Поэтому вы не можете использовать RelativeSource с FindAncestor для вашего объекта.

Вы можете использовать ElementName в своем Binding.Примерно так должно работать:

<UserControl x:Name="userControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Some.Namespace"
    DataContext="{Binding Path=ViewModel, RelativeSource={RelativeSource Self}}">
    <UserControl.Resources>
        <local:SomeClass
            x:Key="SomeClass"
            DataContext="{Binding Path=DataContext, ElementName=userControl}" />
    </UserControl.Resources>
</UserControl>
0 голосов
/ 16 января 2010

когда вы добавляете свой ресурс в визуальное дерево, он должен наследовать контекст данных. но ... взгляните на element spy , он может просто делать то, что вам нужно.

0 голосов
/ 16 января 2010

Что я хотел бы сделать, это создать прикрепленное поведение (ContextualizeResourceBehavior) в пользовательском элементе управления и указать ключ ресурса для этого присоединенного поведения. Поведение будет искать ресурс (не уверен, что вы сможете сделать это при присоединении, в противном случае вам понадобится подключить событие Loaded) и передать контекст данных.

0 голосов
/ 15 января 2010

Я думаю, что вы ищете просто {Binding}, который связывается с унаследованным DataContext. Вот пример, хотя немного странно показывает, как вы можете получить цвет путем привязки к DataContext:

<Window x:Class="AncestorBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <SolidColorBrush x:Key="MyBrush" Color="Blue" />
    </Window.Resources>
    <StackPanel>
        <Button DataContext="{Binding Source={StaticResource MyBrush}}" Content="My Button">
            <Button.Resources>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="Background" Value="{Binding}" />
                </Style>
            </Button.Resources>
        </Button>
    </StackPanel>
</Window>
...