Ответ 1
Ваш тип должен реализовывать INotifyPropertyChanged
, чтобы коллекция могла обнаружить изменения. Как говорит Сэм, передайте string.Empty
в качестве аргумента.
Вам также необходимо, чтобы источник данных ListBox
представлял собой коллекцию, которая предоставляет уведомление об изменении. Это делается через интерфейс INotifyCollectionChanged
(или интерфейс не такой 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.
EDIT 1 Я заметил ваш комментарий, что вы используете коллекцию ListBox.Items
как свою коллекцию. Это не будет требовать привязки. Вам лучше сделать что-то вроде:
var collection = new ObservableCollection<FooBar>();
collection.Add(fooBar1);
_listBox.ItemsSource = collection;
Я не проверял этот код для точности компиляции, но вы получаете суть.
EDIT 2 Использование DataTemplate
, которое я дал выше (я отредактировал его в соответствии с вашим кодом), устраняет проблему.
Кажется странным, что запуск PropertyChanged
не приводит к обновлению элемента списка, но с использованием метода ToString
это не тот способ, которым WPF должен был работать.
Используя этот DataTemplate, пользовательский интерфейс корректно связывается с точным свойством.
Недавно я задал вопрос о выполнении форматирования строк в привязке WPF. Вам может показаться полезным.
EDIT 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>