我对WPF中的另一个有点怪异感到不满。请考虑以下类及其名为IStupid
的{{1}}类型属性:
MyStupid
现在考虑以下绑定到public struct DumbClass
{
public IStupid MyStupid { get { return new IsStupid(); } }
}
public interface IStupid{}
public class IsStupid : IStupid{}
:
ListBox
xaml没有什么特别之处:
var items = new List<DumbClass>(new []{new DumbClass(), new DumbClass(), new DumbClass()});
OptListBox.ItemsSource = items;
正如预期的那样,列表框的输出是3行“MyProject.DumbClass”。
但是,如果我设置<ListBox Name="OptOccurances" Height="238" HorizontalAlignment="Left" Margin="130,34,0,0" VerticalAlignment="Top" Width="229" >
</ListBox>
(或创建一个ItemTemplate,将'MyStupid'直接绑定到模板中的TextBlock),我会得到3个空行,而我预计它会说DisplayMemberPath="MyStupid"
。为什么数据绑定引擎无法调用默认的MyProject.IsStupid
实现并显示类名。是否有接口类型属性的解决方法?至少,有没有理由不抛出绑定错误?
答案 0 :(得分:3)
我可以重现这个问题。它看起来像WPF bug。
以下是您可以使用的解决方法: 您可以使用Item的DataTemplate和StringFormat参数代替DisplayMemberPath,它会强制将属性值转换为字符串:
<ListBox x:Name="OptOccurances" Height="238" HorizontalAlignment="Left" Margin="130,34,0,0" VerticalAlignment="Top" Width="229" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=MyStupid, StringFormat='{}{0}' }"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
通常,您可以使用WPF跟踪设置来找出此类问题:
但在这种情况下,我发现没有发生绑定错误。
此外,您可以使用WPF Visualizer for Visual Studio 2012,它允许您直接从调试Watch调查树:
使用以下代码,您可以获得带有绑定的TextBlock:
private void btn_Click_1(object sender, RoutedEventArgs e)
{
var listBoxItem = OptOccurances.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem;
var item = OptOccurances.Items[1] as DumbClass;
var tbk = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(listBoxItem, 0),0),0) as TextBlock;
var binding = BindingOperations.GetBinding(tbk, TextBlock.TextProperty);
var be = BindingOperations.GetBindingExpression(tbk, TextBlock.TextProperty);
var vs = DependencyPropertyHelper.GetValueSource(tbk, TextBlock.TextProperty);
var val = tbk.GetValue(TextBlock.TextProperty);
}
它表明Binding状态实际上是活动的,并且映射的对象是正确的。显然,Binding的内部结构(PropertyPathWorker)在获取属性的类型属性
时的工作方式不同