【问题标题】:Data bound ListBox won't update数据绑定 ListBox 不会更新
【发布时间】:2011-03-01 05:04:25
【问题描述】:

我创建了一个类 Track,它代表播放列表中的一首歌曲:

public class Track
{
    public Uri Path
    {
        get { return path; }
        set { path = value; }
    }
    public TrackState State
    {
        get { return state; }
        set { state = value; }
    }

    private Uri path;
    private TrackState state;
}

接下来我创建了在 UI 窗口和 Track 类之间交互的 MainWindowController 类:

public class MainWindowController : INotifyPropertyChanged
{
    public ObservableCollection<Track> Playlist
    {
        get { return playlist; }
        set
        {
            if (value != this.playlist)
            {
                playlist = value;
                NotifyPropertyChanged("Playlist");
            }
        }
    }
    public int NowPlayingTrackIndex
    {
        set
        {
            if (value >= 0)
            {
                playlist[nowPlayingTrackIndex].State = TrackState.Played;
                playlist[value].State = TrackState.NowPlaying;
                this.nowPlayingTrackIndex = value;
            }
        }
    }

    private ObservableCollection<Track> playlist;
    private int nowPlayingTrackIndex;
}

基本上,这个类存储播放列表集合和当前播放曲目的索引。最后,我在 WPF 中创建了 UI 窗口:

<Window ...>
... 
<ListBox 
    Name="PlaylistListBox" 
    ItemsSource="{Binding Source={StaticResource ResourceKey=PlaylistViewSource}}" 
    ItemTemplateSelector="{Binding Source={StaticResource ResourceKey=TrackTemplateSelector}}" 
    MouseDoubleClick="PlaylistListBox_MouseDoubleClick" />
... 
</Window>

以及后面对应的代码:

...
private void PlaylistListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    int index = this.PlaylistListBox.SelectedIndex;
    this.windowController.NowPlayingTrackIndex = index;
} 
...

Items 源指向定义CollectionViewSource 的静态资源。 ItemTemplateSelector 定义根据轨道状态(NowPlaying 或 Played)将哪个 DataTemplate 用于列表框项。

当用户双击播放列表项时,MainWindowController 中的NowPlayingTrackIndex 会更新并更新轨道状态。问题是,列表框项目的DataTemplates 不会在窗口上更新,即双击的列表框项目不会更改数据模板。为什么?

我尝试将PropertyChanged 设置为跟踪状态,但没有帮助。我错过了什么?谢谢你。

【问题讨论】:

    标签: wpf binding


    【解决方案1】:

    您的代码中有两个问题需要解决。

    首先,您应该知道ObservableCollection 通知其观察者有关其自身元素的更改,它不知道也不关心其元素属性的更改。换句话说,它不会监视其集合中项目的属性更改通知。因此,更改 PlayList 集合中的 Track 对象属性值无论如何都不会监视。这是关于该主题的article

    其次,您的 MainWindowController 根本不会广播 NowPlayingTrackIndex 属性值更改。您应该致电NotifyPropertyChanged("NowPlayingTrackIndex") 通知感兴趣的各方有关当前播放曲目的更改。这可能会解决您的问题,但更优雅的方式和我的建议是实现一个包含NowPlaying 属性的自定义 ObservableCollection 类(类似于TrackObservableCollection),而不是在看起来像不必要的中介的 MainWindowController 类中实现它。

    【讨论】:

    • 感谢您的回答。我明白为什么我的代码不起作用。但是,我很难实现自己的 ObservableCollection 类扩展。你能举个例子吗?现在当然是一个确切的课程(当然认为那会很棒),但只是为了了解如何实现TrackNowPlaying 属性。您可以发布新答案或编辑此答案。再次感谢您的回答。干杯。
    猜你喜欢
    • 2012-02-29
    • 2012-07-27
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    相关资源
    最近更新 更多