绑定属性声明为接口vs类类型时,WPF绑定行为是否不同?

这开始于我认为与我的ToString()实现相关的奇怪行为,我问了这个问题: 当ToString()有一个协作对象时,为什么WPF数据绑定不显示文本?

事实certificate它与协作者无关,并且可以重现。

当我将Label.Content绑定到声明为接口类型的DataContext的属性时,在运行时对象上调用ToString() ,标签显示结果。

当我将TextBlock.Text绑定到同一属性时,永远不会调用ToString()并且不显示任何内容。 但是 ,如果我将声明的属性更改为接口的具体实现,它将按预期工作。

这是不是设计? 如果是这样,任何想法为什么?

重现:

  • 创建一个新的WPF应用程序(.NET 3.5 SP1)
  • 添加以下类:
 public interface IFoo { string foo_part1 { get; set; } string foo_part2 { get; set; } } public class Foo : IFoo { public string foo_part1 { get; set; } public string foo_part2 { get; set; } public override string ToString() { return foo_part1 + " - " + foo_part2; } } 
 public class Bar { public IFoo foo { get { return new Foo {foo_part1 = "first", foo_part2 = "second"}; } } } 
  • 将Window1的XAML设置为:

        
  • 在Window1.xaml.cs中:

 public partial class Window1 : Window { public Window1() { InitializeComponent(); DataContext = new Bar(); } } 

运行此应用程序时,您将只看到一次文本(位于顶部,标签中)。 如果将Bar类的foo属性类型更改为Foo (而不是IFoo )并再次运行应用程序,则会在两个控件中看到该文本。

我知道这个线程已经老了,但我找到了解决这个问题的方法。 在绑定上使用StringFormat属性:

       

是的,你是对的。 显然, ContentControl.Content属性的实现方式与TextBlock.Text属性不同。 当然,一个明显的区别是ContentControl实际上会为不是Visual的内容对象生成TextBlock实例,并且没有DataTemplateTextBlock没有。 它将自己呈现文本。 在这两种情况下,字符串都由

  1. IValueConverter (如果存在于绑定中)
  2. TypeConverter (如果声明)
  3. object.ToString()

看起来这个算法仅在TextBlockContentControl之间的步骤3中有所不同,如图所示。 虽然ContentControl实际上解析了接口后面的对象,但TextBlock却没有。 有趣。

我想这是你必须要忍受的事情。 你现在有几个选择:

  • 在您的界面上公开一个字符串属性并绑定到该属性
  • 将数据对象公开为具体类而不是接口
  • 使用ContentControl而不是TextBlock
  • 提供IValueConverter并在IValueConverter使用它
  • 为您的界面提供TypeConverter
  • 做别的事(可能还有更多)