You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MediaPlaybackList变更通知未同步至ListView的问题求助

解决MediaPlaybackList变更未通知绑定ListView的问题

嘿,我之前也踩过这个坑!核心问题在于MediaPlaybackList的Items集合本身不支持INotifyCollectionChanged接口——这意味着你往里面加、删、改MediaPlaybackItem的时候,绑定的ListView根本感知不到变化,自然不会更新。

下面给你两种靠谱的解决思路,选哪种看你的需求:

方法一:用ObservableCollection做中间层(推荐)

我们可以自己维护一个支持变更通知的ObservableCollection,同步MediaPlaybackList的Items,然后把ListView绑定到这个集合上。这样既保留了MediaPlaybackList的原生功能,又能让ListView实时响应变化。

ViewModel代码示例:

using System.Collections.ObjectModel;
using Windows.Media.Playback;

public class YourPlayListViewModel
{
    // 供ListView绑定的可观察集合
    private ObservableCollection<MediaPlaybackItem> _playbackItems;
    public ObservableCollection<MediaPlaybackItem> PlaybackItems
    {
        get => _playbackItems;
        set
        {
            _playbackItems = value;
            // 如果用了MVVM框架(比如Prism、MvvmLight),这里调用对应的属性变更通知方法
            // 比如 RaisePropertyChanged(nameof(PlaybackItems));
        }
    }

    // 原生的MediaPlaybackList,供MediaPlayerElement绑定
    public MediaPlaybackList MediaPlaybackList { get; }

    public YourPlayListViewModel()
    {
        MediaPlaybackList = new MediaPlaybackList();
        // 初始化可观察集合
        _playbackItems = new ObservableCollection<MediaPlaybackItem>(MediaPlaybackList.Items);
        // 订阅MediaPlaybackList的ItemsChanged事件,同步集合
        MediaPlaybackList.ItemsChanged += MediaPlaybackList_ItemsChanged;
    }

    private void MediaPlaybackList_ItemsChanged(MediaPlaybackList sender, ItemsChangedEventArgs args)
    {
        // 根据不同的变更类型更新ObservableCollection
        switch (args.Action)
        {
            case ItemsChangedAction.Add:
                PlaybackItems.Insert(args.Index, sender.Items[args.Index]);
                break;
            case ItemsChangedAction.Remove:
                PlaybackItems.RemoveAt(args.Index);
                break;
            case ItemsChangedAction.Move:
                var movedItem = PlaybackItems[args.OldIndex];
                PlaybackItems.RemoveAt(args.OldIndex);
                PlaybackItems.Insert(args.Index, movedItem);
                break;
            case ItemsChangedAction.Replace:
                PlaybackItems[args.Index] = sender.Items[args.Index];
                break;
            case ItemsChangedAction.Reset:
                PlaybackItems.Clear();
                foreach (var item in sender.Items)
                {
                    PlaybackItems.Add(item);
                }
                break;
        }
    }

    // 记得在ViewModel销毁时取消订阅,避免内存泄漏
    public void Cleanup()
    {
        MediaPlaybackList.ItemsChanged -= MediaPlaybackList_ItemsChanged;
    }
}

对应的XAML修改:

把ListView的ItemsSource绑定到我们的PlaybackItems集合:

<ListView x:Name="PlayListView" ItemsSource="{x:Bind ViewModel.PlaybackItems, Mode=OneWay}">
    <!-- 你的ItemTemplate内容 -->
</ListView>

方法二:手动触发ListView绑定刷新(简单但不优雅)

如果不想折腾ObservableCollection,也可以在MediaPlaybackList的ItemsChanged事件里,手动重置ListView的数据源。这种方式虽然简单,但会导致整个列表重新加载,可能有视觉闪烁或者性能问题,适合小型列表场景。

代码示例(在用户控件的代码后台):

public YourPlayListControl()
{
    this.InitializeComponent();
    // 假设ViewModel已经初始化,订阅ItemsChanged事件
    ViewModel.MediaPlaybackList.ItemsChanged += MediaPlaybackList_ItemsChanged;
}

private void MediaPlaybackList_ItemsChanged(MediaPlaybackList sender, ItemsChangedEventArgs args)
{
    // 先清空数据源,再重新赋值,触发绑定刷新
    PlayListView.ItemsSource = null;
    PlayListView.ItemsSource = sender.Items;
}

最后提醒一句:不管用哪种方法,都要记得在页面/控件销毁时取消订阅ItemsChanged事件,不然容易出现内存泄漏哦!

内容的提问来源于stack exchange,提问作者user6189573

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:53:41