Ваш тип должен реализовывать INotifyPropertyChanged
, чтобы коллекция могла обнаружить изменения. Как говорит Сэм, передайте string.Empty
в качестве аргумента.
Вы также должны иметь источник данных ListBox
, представляющий собой коллекцию, которая предоставляет уведомление об изменении. Это делается через интерфейс INotifyCollectionChanged
(или интерфейс not-so-WPF IBindingList
).
Конечно, вам нужен интерфейс INotifyCollectionChanged
, чтобы запускать каждый раз, когда один из элементов INotifyPropertyChanged
запускает свое событие. К счастью, есть несколько типов в структуре, которые предоставляют эту логику для вас. Вероятно, наиболее подходящим является 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, пользовательский интерфейс правильно связывается с точным свойством.
Некоторое время назад я задал вопрос о форматировании строки в привязке WPF . Вы можете найти это полезным.
РЕДАКТИРОВАТЬ 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>