【问题标题】:Add items to ListView only if item is not a duplicate仅当项目不重复时才将项目添加到 ListView
【发布时间】:2016-05-16 00:08:25
【问题描述】:

这几天我一直在旋转我的轮子!

尝试按进程名称(在本例中为“记事本”)将当前正在运行的特定进程的MainWindowTitle 添加到 ListView。我已经弄清楚如何创建和添加项目,但现在我的 ListView 中有重复项。所以我要做的只是将一个项目添加到我的 ListView,如果它在我的 ListView 上不存在作为一个确切的项目。

相关信息:

-我将尝试从多个相同的进程(从 1 到 9)捕获 MainWindowTitle,但它们每个都有一个唯一的 ID。

-每个 MainWindowTitle 都会不同

这是我目前所拥有的,我无法让 LINQ 工作,我不确定是否有办法制作一个 foreach 循环来防止重复。

感谢您的帮助!

Process[] processList = Process.GetProcessesByName("notepad");
    foreach (Process process in processList)
    {
        ListViewItem item = new ListViewItem();
        item.Content = process.MainWindowTitle;
        item.Tag = process;

        if (listView.Items.Contains(item))
        {
            MessageBox.Show("Duplicate");
        }
        else
        {
            MessageBox.Show("New Item!");
            listView.Items.Add(item);
        }

编辑 1:仍然添加重复项

        Process[] processList = Process.GetProcessesByName("notepad");
        foreach (Process process in processList)
        {
            ListViewItem item = new ListViewItem();
            item.Content = process.MainWindowTitle;

            item.DataContext = process;

            var itemz = listView.Items.Cast<ListViewItem>().ToList().Where(x => x.DataContext == process);

            if (listView.Items.Contains(itemz))
            {
                MessageBox.Show("Duplicate");
            }
            else
            {
                MessageBox.Show("New Item!");
                listView.Items.Add(item);
            }

Edit2:更接近,我希望,仍然添加重复项

        Process[] processList = Process.GetProcessesByName("notepad");
        foreach (Process process in processList)
        {
            ListViewItem item = new ListViewItem();
            item.Content = process.MainWindowTitle;

            item.DataContext = process;

            var itemz = listView.Items.Cast<ListViewItem>().ToList().Where(x => (x.DataContext as Process).Id == process.Id);

            if (itemz == null)
            {
                MessageBox.Show("Duplicate");
            }
            else
            {
                MessageBox.Show("New Item!");
                listView.Items.Add(item);
            }
        }

【问题讨论】:

    标签: c# .net wpf winforms


    【解决方案1】:

    与其手动使用项目填充ListView,不如创建一个包含您要显示的唯一窗口标题的ObservableCollection&lt;string&gt;。然后将ListView.ItemsSource 设置为此属性。在这个支持集合上,只要确保只添加不同的东西。所以是这样的:

    查看模型

    public class ValuesViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        public ObservableCollection<string> WindowTitles { get; private set; }
    
        public ValuesViewModel()
        {
            WindowTitles = new ObservableCollection<string>();
        }
    
        public void AddTitleIfUnique(string title)
        {
            if (!WindowTitles.Contains(title))
                WindowTitles.Add(title);
        }
    }
    

    UI XAML

    <ListView ItemsSource="{Binding WindowTitles}"/>
    

    UI 代码背后

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
    
            var viewModel = new ValuesViewModel();
            viewModel.AddTitleIfUnique("Testing");
            viewModel.AddTitleIfUnique("Testing Again");
            viewModel.AddTitleIfUnique("Testing Again");
            DataContext = viewModel;
        }
    }
    

    假设MainWindow 在其XAML 中包含ListView UI XAML 块。这显示了我认为您正在寻找的结果。基本上,我已将添加 if unique 的逻辑移回视图模型并移出视图,就像您在问题中所说的那样,这使得实现逻辑更简单。

    【讨论】:

      【解决方案2】:

      我能想到这段代码不起作用的唯一原因是 ListViewItem 没有重载等号运算符。如果是这种情况,那么当您调用 Contains 时,它会检查对象是否是同一个对象,而这绝不是这种情况,因为您刚刚创建了新对象。为了确保唯一性,我将使用 linq Any 函数而不是 Contains。 Linq Any 检查是否有任何符合给定条件的元素。

      if (listView.Items.Contains(item))//replace this
      if(listView.Items.Any(x=>x.Content == item.Content))//with this 
      

      【讨论】:

      • 感谢您的想法,另一个论坛上有人建议,不幸的是,“ItemCollection”不包含“Any”的定义。
      • Are you using System.Linq; Linq 函数需要 using 语句才能工作。
      • 是的,使用 System.Linq;总体上仍然是一个新程序员,并且是 c# 的新手,但是 .contains 似乎调用了一个“对象”,我相信这就是 Any 无法使用的原因
      【解决方案3】:

      您实际上可以使用 Process 对象作为 ListViewItem 的 DataContext。然后,使用 Process.Id 检查该项目是否已添加。

      var item = listview.Items.Cast<ListViewItem>().ToList().Where(x => x.DataContext == theProcess);
      

      【讨论】:

      • 非常感谢一个例子,我无法使用上述信息触发 if 语句
      • 我已经添加了样本。
      • 对 c# 来说还是很新,这看起来很有希望,虽然,我不确定如何使用它。我是用这个替换一些行,还是这应该是我的新 if 语句?另外,'theProcess' 代表什么与我的代码相关?非常感谢您的帮助!
      • 我只是更喜欢 DataContext 而不是代码中的 Tag。但是这个想法和你之前的“如果”是一样的。现在,当您检查它是否存在时,请使用我的示例。这次,使用 Process 对象的 ID。该项目(来自 var item = ...)如果不存在,将返回 null。
      • 我想我还没有完全理解这个概念:请参阅编辑 1
      猜你喜欢
      • 1970-01-01
      • 2018-09-19
      • 1970-01-01
      • 2012-01-04
      • 1970-01-01
      • 2013-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多