WPF:绑定内部资源部分 - 无法访问DatatContext

时间:2017-05-17 15:34:15

标签: c# wpf data-binding

我在DataTemplate的资源部分中遇到了绑定问题:

<Window
    ...
    DataContext="{Binding RelativeSource={RelativeSource Self}}" >
    ...
    <ItemsControl ItemsSource="{Binding Items}">
        <ItemsControl.Resources>

            <DataTemplate x:Key="TextTemplate">
                <DataTemplate.Resources>
                    <!-- Binding below doesn't seem to work -->
                    <local:FreezableProxyElement x:Key="Proxy" Data="{Binding}" />
                    <local:Message x:Key="Message" Text="{Binding Data, Source={StaticResource Proxy}}" />
                </DataTemplate.Resources>

                <StackPanel Orientation="Horizontal">
                    <Label>Text</Label>
                    <TextBlock Text="{Binding Text, Source={StaticResource Message}}" />
                </StackPanel>
            </DataTemplate>

            <DataTemplate x:Key="IntegerTemplate">
                <StackPanel Orientation="Horizontal">
                    <Label>Integer</Label>
                    <TextBlock Text="{Binding}" />
                </StackPanel>
            </DataTemplate>

        </ItemsControl.Resources>

        <ItemsControl.ItemTemplateSelector>
            <local:DataTypeSelector
                TextTemplate="{StaticResource TextTemplate}"
                IntegerTemplate="{StaticResource IntegerTemplate}"
                />
        </ItemsControl.ItemTemplateSelector>

    </ItemsControl>

道歉(以及人为的例子) - 我试图尽可能简短。重要的部分是第一个Resources的{​​{1}}部分(&#34; TextTemplate&#34;)。

支持代码:

DataTemplate

我始终明白,在资源部分中,public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } public ObservableCollection<object> Items { get; } = new ObservableCollection<object>() { (int)5, "Hello World!" }; } public class Message : DependencyObject { public string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); } public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(Message)); } public class FreezableProxyElement : Freezable { protected override Freezable CreateInstanceCore() => new FreezableProxyElement(); public object Data { get => (object)GetValue(DataProperty); set => SetValue(DataProperty, value); } public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(FreezableProxyElement)); } public class DataTypeSelector : DataTemplateSelector { public DataTemplate TextTemplate { get; set; } public DataTemplate IntegerTemplate { get; set; } public override DataTemplate SelectTemplate(object item, DependencyObject container) { switch (item) { case string s: return TextTemplate; case int i: return IntegerTemplate; default: return null; } } } 派生的对象可以从其容器(在此Freezable中)继承DataContext,应该是来自DataTemplate的项目,这由集合的整数&#34; 5&#34;由&#34; IntegerTemplate&#34;)正确显示来验证。但是,不显示文本字符串并绑定到&#34; FreezeableProxyElement.Data&#34;在&#34; TextTemplate&#34;资源部分产生数据错误:

ItemsControl.ItemsSource

如果System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:(no path); DataItem=null; target element is 'FreezableProxyElement' (HashCode=12379565); target property is 'Data' (type 'Object') 不是FreezableProxyElement派生出来,这是我希望看到的错误。这里的问题是什么,有什么好办法吗?

1 个答案:

答案 0 :(得分:1)

我感到框架中的一种骚动让我怀疑DataTemplate的资源是否过多地脱离了现实。我不确切地知道问题是什么(视觉树,逻辑树,某些东西或其他),但我能够重现它,以下内容适用于我:

<DataTemplate x:Key="TextTemplate">
    <StackPanel Orientation="Horizontal">
        <StackPanel.Resources>
            <local:FreezableProxyElement 
                x:Key="Proxy" 
                Data="{Binding}" 
                />
            <local:Message 
                x:Key="Message" 
                Text="{Binding Data, Source={StaticResource Proxy}}" 
                />
        </StackPanel.Resources>
        <Label>Text</Label>
        <Label 
            Content="{Binding Text, Source={StaticResource Message}}"
            />
    </StackPanel>
</DataTemplate>

我仍然怀疑这是一个XY问题,真正的解决方案是以其他方式创建Message。但是在不知道更多细节的情况下,我无法给出答案。

更新

如何进行绑定跟踪:

Text="{Binding Data, Source={StaticResource Proxy}, PresentationTraceSources.TraceLevel=High}" 
不要把它们留在那个地方,它们会吃掉周期。