解决WPF ListView虚拟化ListViewItem的IsSelected属性MVVM双向绑定bool值后出现的绑定错乱的问题

解决WPF ListView虚拟化ListViewItem的IsSelected属性MVVM双向绑定bool值后出现的绑定错乱的问题在一次使用WPFListView的时候,我发现在MVVM模式下在ListView开启虚拟化的情况下,将ListViewItem的IsSelected属性与一个对应的布尔值进行双向绑定。文档目录结构如下:源码如下:NotifyBase.csusingSystem.ComponentModel;usingSystem.Runtime.CompilerServices;namespaceWpfApp10{publicclassNotifyBase:INotifyProp

在一次使用WPF ListView的时候,我发现在MVVM模式下在ListView开启虚拟化的情况下,将ListViewItem的IsSelected属性与一个对应的布尔值进行双向绑定。

文档目录结构如下:
在这里插入图片描述
源码如下:

NotifyBase.cs

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WpfApp10
{
    public class NotifyBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        
        public void DoNotify([CallerMemberName]string name = "")
        {
        	// 提醒界面更新绑定的属性
            PropertyChanged?.Invoke(name, new PropertyChangedEventArgs(name));
        }
    }
}

MainViewModel.cs(还另外包含一个Demo类型与ListViewItem进行数据绑定)

using System.Collections.ObjectModel;

namespace WpfApp10
{
    public class MainViewModel : NotifyBase
    {
        private ObservableCollection<Demo> _demoCollection;
        public ObservableCollection<Demo> DemoCollection
        {
            get
            {
                return _demoCollection;
            }
            set
            {
                _demoCollection = value;
                DoNotify();
            }
        }

        public MainViewModel()
        {
            DemoCollection = new ObservableCollection<Demo>();
            for(int i = 0; i < 1000; i++)
            {
                DemoCollection.Add(new Demo
                {
                    Index = i,
                    Name = "name" + i,
                    IsSelected = false
                });
            }
        }
    }

    public class Demo : NotifyBase
    {
        private int _index;
        public int Index
        {
            get
            {
                return _index;
            }
            set
            {
                _index = value;
                DoNotify();
            }
        }

        private string _name;
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
                DoNotify();
            }
        }

        private bool _isSelected;
        public bool IsSelected
        {
            get
            {
                return _isSelected;
            }
            set
            {
                _isSelected = value;
                DoNotify();
            }
        }
    }
}

MainWindow.xaml

<Window x:Class="WpfApp10.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp10"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainViewModel x:Name="vm"/>
    </Window.DataContext>
    <Grid>
        <ListView ItemsSource="{Binding DemoCollection}" Margin="20">
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.View>
                <GridView>
                    <GridViewColumn Width="80" Header="下标" DisplayMemberBinding="{Binding Index}"/>
                    <GridViewColumn Width="100" Header="姓名" DisplayMemberBinding="{Binding Name}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

MainWindow.xaml.cs

using System.Threading.Tasks;
using System.Windows;

namespace WpfApp10
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

操作如下:
先鼠标左键单击一行。
在这里插入图片描述
同时按下Shift与鼠标左键。
在这里插入图片描述
单击显示为第二行(显示为1)当前View其他ListViewItem选中状态被清空。
在这里插入图片描述
翻至下面的View发现选中较为错乱,很多应该被取消选中的的ListViewItem依然是被选中的状态。
在这里插入图片描述
通过百度找了很多博客看了以后,终于找到一种现在看来较为可行的办法,因为之前查找不易,特来记录:
在这里插入图片描述
那就是在ListView的SelectionChanged事件中加入:

private void ListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
 {
      foreach(Demo demo in e.AddedItems.OfType<Demo>())
      {
          demo.IsSelected = true;
      }

      foreach(Demo demo in e.RemovedItems.OfType<Demo>())
      {
          demo.IsSelected = false;
      }
  }

反复操作了十几次,问题没有复现,暂定为问题已解决。大家还有其他方法吗?如果有的话感谢分享哟!

今天的文章解决WPF ListView虚拟化ListViewItem的IsSelected属性MVVM双向绑定bool值后出现的绑定错乱的问题分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/31977.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注