我在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
派生出来,这是我希望看到的错误。这里的问题是什么,有什么好办法吗?
答案 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}"
不要把它们留在那个地方,它们会吃掉周期。