您的类型应该实现INotifyPropertyChanged 以便集合可以检测到更改。正如 Sam 所说,将 string.Empty 作为参数传递。
您还需要将ListBox 的数据源设为提供更改通知的集合。这是通过 INotifyCollectionChanged 接口(或非 WPF IBindingList 接口)完成的。
当然,每当INotifyPropertyChanged 成员之一触发其事件时,您都需要触发INotifyCollectionChanged 接口。值得庆幸的是,框架中有一些类型可以为您提供这种逻辑。可能最合适的是ObservableCollection<T>。如果您将ListBox 绑定到ObservableCollection<FooBar>,则事件链接将自动发生。
在相关说明中,您不必使用ToString 方法来让 WPF 以您想要的方式呈现对象。您可以像这样使用DataTemplate:
<ListBox x:Name="listBox1">
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:FooBar}">
<TextBlock Text="{Binding Path=Property}"/>
</DataTemplate>
</ListBox.Resources>
</ListBox>
通过这种方式,您可以控制对象所属的对象的呈现方式——在 XAML 中。
编辑 1 我注意到您的评论说您正在使用 ListBox.Items 集合作为您的集合。这不会进行所需的绑定。你最好做这样的事情:
var collection = new ObservableCollection<FooBar>();
collection.Add(fooBar1);
_listBox.ItemsSource = collection;
我没有检查该代码的编译准确性,但你明白了。
编辑 2 使用我在上面给出的DataTemplate(我对其进行了编辑以适合您的代码)解决了问题。
触发PropertyChanged 不会导致列表项更新似乎很奇怪,但是使用ToString 方法并不是WPF 的预期工作方式。
使用此 DataTemplate,UI 可以正确绑定到确切的属性。
不久前我在这里问了一个关于 string formatting in a WPF binding 的问题。您可能会发现它很有帮助。
编辑 3 我很困惑为什么这仍然不适合你。这是我正在使用的窗口的完整源代码。
后面的代码:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
namespace StackOverflow.ListBoxBindingExample
{
public partial class Window1
{
private readonly FooBar _fooBar;
public Window1()
{
InitializeComponent();
_fooBar = new FooBar("Original value");
listBox1.ItemsSource = new ObservableCollection<FooBar> { _fooBar };
}
private void button1_Click(object sender, RoutedEventArgs e)
{
_fooBar.Property = "Changed value";
}
}
public sealed class FooBar : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string m_Property;
public FooBar(string initval)
{
m_Property = initval;
}
public string Property
{
get { return m_Property; }
set
{
m_Property = value;
OnPropertyChanged("Property");
}
}
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
XAML:
<Window x:Class="StackOverflow.ListBoxBindingExample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:StackOverflow.ListBoxBindingExample"
Title="Window1" Height="300" Width="300">
<DockPanel LastChildFill="True">
<Button Click="button1_Click" DockPanel.Dock="Top">Click Me!</Button>
<ListBox x:Name="listBox1">
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:FooBar}">
<TextBlock Text="{Binding Path=Property}"/>
</DataTemplate>
</ListBox.Resources>
</ListBox>
</DockPanel>
</Window>