当绑定项更改时,WPF ListBox不更新绑定项的值



在应用程序中,有一个Listbox绑定到ObservableCollection,然后所选项目将自身绑定到一些标签:当标签中项目的属性发生更改时,实际对象(在本例中为Multimedia(会更新(正如我调试的那样(,但列表框不会更新显示的值。

Multimedia类实现了INotifyPropertyChanged,但我不确定我是否正确使用了它。

其他一切都在正常工作(添加按钮向列表中添加了一个新元素,并按原样显示(。

我在不同的论坛和stackoverflow上查看了一下,并尝试了不同的变体,但当属性更新时,它仍然没有在ListBox中更新。

这是XMAL:

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="135" />
<RowDefinition Height="*" />
<RowDefinition Height="45" />
</Grid.RowDefinitions>
<ListBox Name="mediaListBox"  ItemsSource="{Binding Path=MyData}" Grid.Row="0"/>
<Grid Grid.Row="1"  DataContext="{Binding ElementName=mediaListBox, Path=SelectedItem}">
...
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=Title}" />
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path=Artist}" />
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=Genre}" />
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Path=Type}" />
</Grid>
<Button Name="cmdAddMedia" Grid.Row="1" Click="cmdAddMedia_Click" Height="45" Margin="0,0,0,2" Grid.RowSpan="2" VerticalAlignment="Bottom">Add Item</Button>
</Grid>

然后这里是主窗口的C#代码:

public partial class MainWindow : Window
{
public MultiMediaList MyData { get; set; }
public void AddStuff()
{
MyData.Add(new Multimedia() { Title = "My Way", Artist = "Calvin Harris", Genre = "Pop", Type = Multimedia.MediaType.CD });
MyData.Add(new Multimedia() { Title = "Inglorious Bastards", Artist = "Quentin Tarantino", Genre = "Violence", Type = Multimedia.MediaType.DVD });
}
public MainWindow()
{
MyData = new MultiMediaList();
AddStuff();
InitializeComponent();
DataContext = this;            
}
...
}

最后是多媒体类和多媒体列表类:

public class Multimedia : INotifyPropertyChanged
{
public enum MediaType { CD, DVD };
private string _title;
private string _artist;
private string _genre;
private MediaType _type;
public string Title
{
get { return _title; }
set
{
_title = value;
NotifyPropertyChanged("Title");
}
}
...
public override string ToString()
{
return _title + " - " + _artist + " [" + _genre + "] - " + getTypeString();
}
private string getTypeString()
{
if(Type == MediaType.CD) { return "CD"; }
else { return "DVD"; }
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}

MultimediaList只是一个从ObservableCollection 继承的空类

public class MultiMediaList: ObservableCollection<Multimedia>
{
}

如果你需要,我也可以上传完整的代码

希望你能帮助我,告诉我我做错了什么。

显然,如果Multimedia对象的属性发生变化,ListBox就会自动调用该对象的ToString()方法。事实并非如此。

与其依赖ToString,不如为ListBox声明一个合适的ItemTemplate:

<ListBox Name="mediaListBox" ItemsSource="{Binding MyData}" Grid.Row="0">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding Title}"/>
<Run Text="-"/>
<Run Text="{Binding Artist}"/>
<Run Text="["/><Run Text="{Binding Genre}"/><Run Text="]"/>
<Run Text="{Binding Type}"/>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

文本块可能写得更短:

<TextBlock>
<Run Text="{Binding Title}"/> - <Run Text="{Binding Artist}"/> [<Run Text="{Binding Genre}"/>] <Run Text="{Binding Type}"/>
</TextBlock>

最新更新