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

MVVM模式下如何通过代码选中自定义ListView多行?

解决MVVM模式下自定义ListView多行选中同步问题

看起来你遇到的核心问题是自定义ListView的SelectedItemsList双向绑定只实现了UI到ViewModel的单向同步,ViewModel到UI的反向同步没有正确工作。结合你提供的代码,我来一步步帮你修复:

1. 修复自定义SrListView的双向绑定逻辑

你之前尝试添加OnSelectedItemsListChanged回调,但只调用了SetSelectedItems,这里有几个关键问题需要完善:

  • 要避免循环触发:当我们从ViewModel同步到UI时,会触发SelectionChanged事件,这时候不能再把SelectedItems赋值回SelectedItemsList,否则会形成循环。
  • 需要监听集合的动态变化:如果ViewModel里的集合是支持通知的类型,当你执行Add/Clear操作时,需要同步到ListView的选中项,而不仅仅是依赖属性值变化的时候。

修改后的SrListView核心代码如下:

public static readonly DependencyProperty SelectedItemsListProperty =
    DependencyProperty.Register(
        nameof(SelectedItemsList),
        typeof(IList),
        typeof(SrListView),
        new FrameworkPropertyMetadata(
            null,
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
            OnSelectedItemsListChanged));

private IList _previousSelectedItemsList;
private bool _isUpdatingFromViewModel;

public IList SelectedItemsList
{
    get => (IList)GetValue(SelectedItemsListProperty);
    set => SetValue(SelectedItemsListProperty, value);
}

private static void OnSelectedItemsListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (d is SrListView listView)
    {
        // 取消订阅之前集合的变化事件
        if (listView._previousSelectedItemsList is INotifyCollectionChanged oldCollection)
        {
            oldCollection.CollectionChanged -= listView.OnSelectedItemsListCollectionChanged;
        }

        // 订阅新集合的变化事件
        if (e.NewValue is INotifyCollectionChanged newCollection)
        {
            newCollection.CollectionChanged += listView.OnSelectedItemsListCollectionChanged;
        }

        listView._previousSelectedItemsList = e.NewValue as IList;
        // 同步初始选中项
        listView.UpdateSelectedItemsFromViewModel();
    }
}

private void OnSelectedItemsListCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    UpdateSelectedItemsFromViewModel();
}

private void UpdateSelectedItemsFromViewModel()
{
    if (SelectedItemsList == null) return;

    _isUpdatingFromViewModel = true;
    try
    {
        SelectedItems.Clear();
        foreach (var item in SelectedItemsList)
        {
            // 确保item在ItemsSource中存在,否则无法选中
            if (Items.Contains(item))
            {
                SelectedItems.Add(item);
            }
        }
    }
    finally
    {
        _isUpdatingFromViewModel = false;
    }
}

private void SrListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // 只有当变化来自UI时,才同步到ViewModel
    if (!_isUpdatingFromViewModel && SelectedItemsList != null)
    {
        SelectedItemsList.Clear();
        foreach (var item in SelectedItems)
        {
            SelectedItemsList.Add(item);
        }
    }
}

2. 优化ViewModel中的集合类型

你当前用的是IList,如果直接用ArrayList或者普通List,当你调用Clear()/Add()时,不会触发INotifyCollectionChanged,也就无法通知ListView同步。建议改用强类型的ObservableCollection<T>,这样集合的变化会自动触发UI更新:

// 把T替换成你的Package实体类型,比如DTO_Package
private ObservableCollection<DTO_Package> _ilSelectedPackages = new ObservableCollection<DTO_Package>();

public ObservableCollection<DTO_Package> ilSelectedPackages
{
    get => _ilSelectedPackages;
    set
    {
        if (_ilSelectedPackages != value)
        {
            _ilSelectedPackages = value;
            OnPropertyChanged(nameof(ilSelectedPackages));
        }
    }
}

3. XAML绑定调整

确保你的ListView的SelectionMode设置正确(已经是Extended,没问题),绑定可以去掉UpdateSourceTrigger,因为双向绑定默认会在合适的时机更新:

<CustomListView SelectionMode="Extended" 
                ItemsSource="{Binding ocPackages}" 
                SelectedItem="{Binding objSelectedPackage}" 
                SelectedItemsList="{Binding ilSelectedPackages, Mode=TwoWay}">
</CustomListView>

关键注意点

  • 确保你要选中的objDTO_PackageToSelect确实存在于ocPackages集合中,否则ListView无法找到该item进行选中。
  • 如果你的ocPackages是ObservableCollection,当集合内容变化时,要确保选中项的同步逻辑正常。

这样修改后,你在ViewModel中执行:

ilSelectedPackages.Clear();
ilSelectedPackages.Add(objDTO_PackageToSelect);

ListView就会自动选中对应的项了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:54:00