Ihr Typ sollte INotifyPropertyChanged
implementieren, damit eine Sammlung die Änderungen erkennen kann. Wie Sam sagt, übergeben Sie string.Empty
als Argument.
Sie müssen die ListBox
Datenquelle eine Sammlung sein, die Änderungsbenachrichtigung bereitstellt. Dies geschieht über die Schnittstelle INotifyCollectionChanged
(oder die nicht-so-WPF IBindingList
Schnittstelle).
Natürlich muss die Schnittstelle INotifyCollectionChanged
ausgelöst werden, wenn eines der Elemente des Elements INotifyPropertyChanged
das Ereignis auslöst. Glücklicherweise gibt es ein paar Typen im Framework, die diese Logik für Sie bereitstellen. Wahrscheinlich am besten geeignet ist ObservableCollection<T>
. Wenn Sie Ihre ListBox
an eine ObservableCollection<FooBar>
binden, wird die Ereignisverkettung automatisch erfolgen.
Zu einem verwandten Hinweis müssen Sie keine ToString
Methode nur verwenden, um WPF zu erhalten, das Objekt auf die gewünschte Weise zu rendern. Sie können eine DataTemplate
wie folgt verwenden:
<ListBox x:Name="listBox1">
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:FooBar}">
<TextBlock Text="{Binding Path=Property}"/>
</DataTemplate>
</ListBox.Resources>
</ListBox>
Auf diese Weise können Sie die Präsentation des Objekts steuern kann, wo er hingehört - in der XAML.
EDIT 1 Ich bemerkte Ihren Kommentar, dass Sie die ListBox.Items
Sammlung als Ihre Sammlung verwenden. Dies wird nicht die erforderliche Bindung machen. Sie sind besser dran, etwas wie:
var collection = new ObservableCollection<FooBar>();
collection.Add(fooBar1);
_listBox.ItemsSource = collection;
Ich habe diesen Code für die Kompiliergenauigkeit nicht überprüft, aber Sie erhalten den Kern.
EDIT 2 Mit der DataTemplate
habe ich oben (ich habe es bearbeitet, um Ihren Code zu passen) behebt das Problem.
Es scheint seltsam, dass das Auslösen von PropertyChanged
nicht zu einer Aktualisierung des Listenelements führt, aber die Verwendung der ToString
-Methode ist nicht die Methode, die WPF verwenden sollte.
Mit diesem DataTemplate wird die UI korrekt an die exakte Eigenschaft gebunden.
Ich habe eine Frage hier eine Weile zurück zu tun string formatting in a WPF binding. Vielleicht finden Sie es hilfreich.
EDIT 3 Ich bin verwirrt, warum dies immer noch nicht funktioniert für Sie. Hier ist der vollständige Quellcode für das Fenster, das ich verwende.
-Code hinter:
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>
Ich habe meine Antwort aktualisiert, um zu zeigen, wie Sie das zum Laufen bringen können. Scheint, dass das DataTemplate der richtige Weg ist. –