【问题标题】:c# wpf store DataGrid collection localy and filter with Textboxc# wpf 本地存储DataGrid集合并使用文本框进行过滤
【发布时间】:2014-11-05 10:07:45
【问题描述】:

我创建了一个简单的 wmi 查询,然后创建了一个自定义集合。 我添加了一个过滤器,该过滤器从文本更改事件的文本框中获取字符串。 它按预期工作,但有一个主要缺点,每次您尝试过滤它实际上都是在进行查询。我想要它做的是本地存储集合并对该本地变量进行操作,而不是一遍又一遍地进行 wmi 查询。 我已经尝试了多种方法,但到目前为止还没有运气。 任何帮助将不胜感激! :)

这是我尝试过的一种方法...

主要cs:

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;

namespace myfilter
{
    public partial class FilteringSample : Window
    {
        public FilteringSample()
        {
            InitializeComponent();

            myProcesses items = new myProcesses();
            lvUsers.ItemsSource = items.GetProcesses;

            CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lvUsers.ItemsSource);
            view.Filter = UserFilter;
        }

        private bool UserFilter(object item)
        {
            if (String.IsNullOrEmpty(txtFilter.Text))
                return true;
            else
                return ((item as myProcess).Name.IndexOf(txtFilter.Text, StringComparison.OrdinalIgnoreCase) >= 0);
        }

        private void txtFilter_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
        {
            CollectionViewSource.GetDefaultView(lvUsers.ItemsSource).Refresh();
        }
    }
}

类cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Text;
using System.Threading.Tasks;

namespace myfilter
{
    class myProcesses
    {
        public IEnumerable<myProcess> GetProcesses
        {
            get
            {
                ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process");
                ManagementObjectCollection processList = searcher.Get();
                myProcess myproc;
                foreach (ManagementObject obj in processList)
                {
                    if (obj != null)
                    {
                        myproc = new myProcess();
                        try
                        {
                            myproc.Name = obj["Name"].ToString();
                        }
                        catch { }
                        try
                        {
                            myproc.ID = obj["ProcessId"].ToString();
                        }
                        catch { }

                        yield return myproc;
                    }
                }
            }
        }
    }

    class myProcess
    {
        public string Name { get; set; }
        public string ID { get; set; }
    }
}

XAML:

<Window x:Class="myfilter.FilteringSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="FilteringSample" Height="200" Width="300">
    <DockPanel Margin="10">
        <TextBox DockPanel.Dock="Top" Margin="0,0,0,10" Name="txtFilter" TextChanged="txtFilter_TextChanged" />
        <DataGrid Name="lvUsers">

        </DataGrid>
    </DockPanel>
</Window

>

【问题讨论】:

    标签: c# wpf datagrid filter collectionview


    【解决方案1】:

    好吧,我想我自己设法弄明白了。 我将数据存储在一个

    ObservableCollection<>
    

    这让我可以在本地检查过滤器结果,并且不会再次重新启动查询。 因此,如果有人感兴趣,这里是修改后的代码(仅在主 cs 中进行了更改):

    namespace filter
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            ObservableCollection<myProcess> myCollection;
            public MainWindow()
            {
                InitializeComponent();
    
                myProcesses items = new myProcesses();
                myCollection = new ObservableCollection<myProcess>();
                foreach (myProcess localproc in items.GetProcesses)
                {
                    myCollection.Add(localproc);
                }
                lvUsers.ItemsSource = myCollection;
    
                CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(myCollection);
                view.Filter = UserFilter;
            }
    
            private bool UserFilter(object item)
            {
                if (String.IsNullOrEmpty(txtFilter.Text))
                    return true;
                else
                    return ((item as myProcess).Name.IndexOf(txtFilter.Text, StringComparison.OrdinalIgnoreCase) >= 0);
            }
    
            private void txtFilter_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
            {
                CollectionViewSource.GetDefaultView(myCollection).Refresh();
            }
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      您似乎遇到的问题是您正在 UI(调度程序)线程上完成所有工作(查询 WMI)。如果您希望 UI 在用户使用应用程序时保持响应,而不是“白屏”或冻结,您将不得不使用异步方法来查询数据。

      .Net 框架的几个部分可帮助您解决此问题:

      • TPL(任务
      • BackgroundWorker 类,
      • 线程类,

      举几个例子,另外还有像 Rx(.Net 的反应式扩展)这样的技术,它封装并提供了一个非常明确的 API 来处理异步问题。

      无论您选择哪种解决方案,您都必须处理从后台线程更新 UI,有很多关于如何在 SO 上执行此操作的示例。

      当然,在您的程序中引入异步执行通常会增加任何代码库的复杂性,尤其是 UI 代码,但如果您希望您的应用程序从用户的角度保持高性能,这就是成本。

      毕竟,如果您不想使用异步方法,您可以在 myProcesses 类中缓存 WMI 查询的结果一段特定的时间,比如说 1 分钟,这样任何未来的请求都会返回这些结果而不是执行另一个查询,一旦 1 分钟到期,您将清除缓存的结果,未来的查询将再次针对 WMI 执行,再次重复该过程。

      【讨论】:

      • 我在想一些类似于 asp 上的数据集的东西。例如,您可以查询 sql server,但将表存储在数据集上并对数据集进行操作...
      猜你喜欢
      • 1970-01-01
      • 2011-03-02
      • 2017-09-02
      • 2019-07-16
      • 2014-02-14
      • 2021-10-02
      • 2021-08-13
      • 2011-05-09
      相关资源
      最近更新 更多