WPF绑定行为时绑定属性声明为接口VS类的类型有什么不同?绑定、有什么不同、属性、接口

2023-09-04 10:28:10 作者:那一抹浅笑、隱藏忧伤

这开始怪异的行为,我认为是绑在我的执行中的ToString(),我问这个问题:http://stackoverflow.com/questions/2916068/why-wont-wpf-databindings-show-text-when-tostring-has-a-collaborating-object

原来什么都没有做的合作者,是可重复的。

当我绑定 Label.Content 来的财产的DataContext 声明为接口类型,的ToString()被称为运行时对象上,并在标签中显示结果。

WPF 命令绑定的各种方式

当我绑定 TextBlock.Text 以相同的属性,的ToString()不会被调用,并没有任何显示。 但是,如果我的声明​​的属性更改为具体实现的接口,它按预期工作。

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

要重现:

创建一个新的WPF应用程序(.NET 3.5 SP1) 添加以下类:

 公共接口的IFoo
{
    字符串foo_part1 {获得;组; }
    字符串foo_part2 {获得;组; }
}

公共类Foo:IFoo的
{
    公共字符串foo_part1 {获得;组; }

    公共字符串foo_part2 {获得;组; }

    公共重写字符串的ToString()
    {
        返回foo_part1 + - + foo_part2;
    }
}
 

 公共类酒吧
{
    公共IFoo的FOO
    {
        {返回新的Foo {foo_part1第一次=,foo_part2 =第二}; }
    }
}
 

设置窗口1的XAML为:

 <窗​​口x:类=WpfApplication1.Window1
     的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
     的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
     标题=窗口1高度=300宽度=300>
     < StackPanel的>
        <标签内容={结合FOO,模式=默认}/>
        < TextBlock的文本={结合FOO,模式=默认}/>
    < / StackPanel的>
< /窗>
 

在Window1.xaml.cs:

 公共部分类窗口1:窗口
{
    公共窗口1()
    {
        的InitializeComponent();
        DataContext的=新的酒吧();
    }
}
 

当您运行此应用程序,你会看到文本只有一次(在顶部,在标签)。如果您更改属性的类型上酒吧(而不是的IFoo ),并再次运行应用程序,你会看到两个控件中的文本。

解决方案

我知道这个线程是旧的,但我发现了一个解决此问题。使用的StringFormat属性上的绑定:

 <窗​​口x:类=WpfApplication1.Window1
     的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
     的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
     标题=窗口1高度=300宽度=300>
     < StackPanel的>
        <标签内容={结合FOO,模式=默认}/>
        < TextBlock的文本={结合FOO,模式=默认,的StringFormat = {} {0}}/>
    < / StackPanel的>
< /窗>
 

This started with weird behaviour that I thought was tied to my implementation of ToString(), and I asked this question: http://stackoverflow.com/questions/2916068/why-wont-wpf-databindings-show-text-when-tostring-has-a-collaborating-object

It turns out to have nothing to do with collaborators and is reproducible.

When I bind Label.Content to a property of the DataContext that is declared as an interface type, ToString() is called on the runtime object and the label displays the result.

When I bind TextBlock.Text to the same property, ToString() is never called and nothing is displayed. But, if I change the declared property to a concrete implementation of the interface, it works as expected.

Is this somehow by design? If so, any idea why?

To reproduce:

Create a new WPF Application (.NET 3.5 SP1) Add the following classes:

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"}; } 
    }
}

Set the XAML of Window1 to:

<Window x:Class="WpfApplication1.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">
     <StackPanel>
        <Label Content="{Binding foo, Mode=Default}"/>
        <TextBlock Text="{Binding foo, Mode=Default}"/>
    </StackPanel>
</Window>

in Window1.xaml.cs:

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

When you run this application, you'll see the text only once (at the top, in the label). If you change the type of foo property on Bar class to Foo (instead of IFoo) and run the application again, you'll see the text in both controls.

解决方案

I know this thread is old but I found a workaround for this problem. Use the StringFormat property on the binding:

<Window x:Class="WpfApplication1.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">
     <StackPanel>
        <Label Content="{Binding foo, Mode=Default}"/>
        <TextBlock Text="{Binding foo, Mode=Default, StringFormat={}{0}}"/>
    </StackPanel>
</Window>