Su tipo debe implementar INotifyPropertyChanged
para que una colección pueda detectar los cambios. Como dice Sam, pase string.Empty
como argumento.
Usted también necesita tener la fuente de datos ListBox
ser una colección que proporciona notificación de cambio. Esto se hace a través de la interfaz INotifyCollectionChanged
(o la interfaz no tan WPF IBindingList
).
Por supuesto, necesita la interfaz INotifyCollectionChanged
para disparar cada vez que uno de los elementos INotifyPropertyChanged
activa su evento. Afortunadamente hay algunos tipos en el marco que proporcionan esta lógica para usted. Probablemente el más adecuado es ObservableCollection<T>
. Si vincula su ListBox
a un ObservableCollection<FooBar>
, el encadenamiento de eventos se realizará automáticamente.
En una nota relacionada, no tiene que usar un método ToString
solo para que WPF renderice el objeto de la manera que desee. Puede utilizar un DataTemplate
así:
<ListBox x:Name="listBox1">
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:FooBar}">
<TextBlock Text="{Binding Path=Property}"/>
</DataTemplate>
</ListBox.Resources>
</ListBox>
De esta manera se puede controlar la presentación del objeto donde pertenece - en el XAML.
EDIT 1 Me di cuenta de que está utilizando la colección ListBox.Items
como su colección. Esto no hará el enlace requerido. Es mejor que hacer algo como:
var collection = new ObservableCollection<FooBar>();
collection.Add(fooBar1);
_listBox.ItemsSource = collection;
No he comprobado que codifican para la compilación exactitud, pero se obtiene la esencia.
EDIT 2 Usando el DataTemplate
di más arriba (lo edité para adaptarlo a su código) corrige el problema.
Parece extraño que disparar PropertyChanged
no haga que el elemento de la lista se actualice, pero luego usar el método ToString
no es la manera en que se pretendía que funcionara WPF.
Al usar este DataTemplate, la UI se une correctamente a la propiedad exacta.
Hice una pregunta aquí hace un tiempo sobre hacer string formatting in a WPF binding. Es posible que lo encuentre útil.
EDIT 3 Estoy desconcertado de por qué esto todavía no funciona para usted. Aquí está el código fuente completo de la ventana que estoy usando.
Código atrás:
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>
He actualizado mi respuesta para mostrar cómo puede hacer que funcione. Parece que DataTemplate es el camino a seguir. –