我创建了一个简单的wmi查询,然后创建了一个自定义集合。 我添加了一个过滤器,它从文本更改事件的文本框中获取字符串。 它按预期工作但有一个主要缺点,每次你尝试过滤它实际上都在进行查询。我想要它做的是存储集合localy并在该局部var上进行操作,而不是一遍又一遍地执行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();
}
}
}
class 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
&GT;
答案 0 :(得分:0)
您似乎遇到的问题是您正在UI(调度程序)线程上执行所有工作(查询WMI)。如果您希望用户界面保持响应状态而不是白屏&#39;或者在用户使用您将要使用异步方法查询数据的应用程序时冻结。
.Net框架的几个部分可以帮助您:
有几个例子,另外还有像Rx(.Net的Reactive Extensions)这样的技术,它们封装并提供了一个定义良好的API来处理异步问题。
您选择哪种解决方案,您将不得不处理从后台线程更新UI的问题,有很多关于如何在SO上执行此操作的示例。
当然,在程序中引入异步执行通常会增加任何代码库的复杂性,尤其是UI代码,但如果您希望应用程序从用户角度保持高性能,则需要付出代价。
毕竟,如果你不想使用异步方法,你可以将myProcesses类中WMI查询的结果缓存一段特定的时间,比如1分钟,所以任何将来的请求将返回这些结果而不是执行另一个查询,一旦1分钟过期,您将清除缓存的结果,并且将针对WMI执行将来的查询,再次重复该过程。
答案 1 :(得分:0)
好吧我想我自己弄明白了。 我将数据存储在
中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();
}
}
}