如何将搜索应用于 MVVM (WPF) 中的列表而不每次都调用列表值?
How to apply search to the list in the MVVM (WPF) without recalling the list values every time?
首先,我是 MVVM 的新手,如果我遗漏了重点,请随时纠正我。
我正在开发使用 MVVM 社区工具包的 WPF 应用程序。我的应用程序架构看起来更像这样:
- 我有简单的
Model
包含一些基本属性
public class Package : ObservableObject
{
private string id;
public string Id
{
get => id;
set => SetProperty(ref id, value);
}
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
private string version;
public string Version
{
get => version;
set => SetProperty(ref version, value);
}
private string summary;
public string Summary
{
get => summary;
set => SetProperty(ref summary, value);
}
}
- 有
ViewModel
,其中有 IList<Package>
属性 和 AsyncRelayCommand
调用进程,获取输出并更新 属性。
class MainWindowViewModel : ObservableObject
{
public AsyncRelayCommand StartProcessCommand { get; }
public MainWindowViewModel()
{
StartProcessCommand = new AsyncRelayCommand(StartProcess, CanStartProcess);
}
private async Task StartProcess()
{
//Start process, collect the output and set the PackageList property
}
private IList<Package> packagesList;
public IList<Package> PackagesList
{
get => packagesList;
set => SetProperty(ref packagesList, value);
}
}
- 然后有一个
View
绑定如下:
<ListView ItemsSource="{Binding PackagesList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}"/>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Version" DisplayMemberBinding="{Binding Version}" />
<GridViewColumn Header="Summary" DisplayMemberBinding="{Binding Summary}"/>
</GridView>
</ListView.View>
</ListView>
和调用 RelayCommand 的按钮(异步)。
这是我面临的问题
我想应用搜索 TextBox
来动态搜索 IList<Package>
的结果,为此我在 ViewModel
中创建了一个 SearchText
在 PropertyChanged
事件上更新 IList<Package>
属性。问题是我的 属性 正在改变,我想 不记得 每次都从过程中回忆它。
- 创建列表
- 搜索列表并将其呈现在视图中
- 如果我要删除我的 searchText 值,它仍然显示从点 1 开始的列表
实现此目标的最佳方法是什么?
到目前为止我已经到了,但只工作了一次,过滤列表但不返回到之前的列表:
public void SearchItem()
{
PackagesList = packagesList.Where(package => package.Id == SearchText).ToList();
}
private string? searchText;
public string? SearchText
{
get => searchText;
set
{
SetProperty(ref searchText, value);
SearchItem();
}
}
按照你的说法,你想在删除文本后显示所有数据?
如果是这样,你可以试试这个
public void SearchItem()
{
PackagesList = packagesList.Where(package => package.Id == SearchText || null == SearchText).ToList();
}
在 MainWindowViewModel
中创建另一个 属性 IList<Package>
并将其命名为 ResultList
private IList<Package> ResultList { get; set;} // Add Result list
private IList<Package> packagesList;
public IList<Package> PackagesList
{
get => packagesList;
set => SetProperty(ref packagesList, value);
}
改为将 ItemsSource 绑定设置为 ResultList
。
<ListView ItemsSource="{Binding ResultList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}"/>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Version" DisplayMemberBinding="{Binding Version}" />
<GridViewColumn Header="Summary" DisplayMemberBinding="{Binding Summary}"/>
</GridView>
</ListView.View>
</ListView>
任何时候您设置 PackagesList
,您也会设置 ResultList
。现在,当它进入搜索时,你会做一些这样的事情
public void SearchItem()
{
ResultList = packagesList.Where(package => package.Id == SearchText).ToList();
}
首先,我是 MVVM 的新手,如果我遗漏了重点,请随时纠正我。
我正在开发使用 MVVM 社区工具包的 WPF 应用程序。我的应用程序架构看起来更像这样:
- 我有简单的
Model
包含一些基本属性
public class Package : ObservableObject
{
private string id;
public string Id
{
get => id;
set => SetProperty(ref id, value);
}
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
private string version;
public string Version
{
get => version;
set => SetProperty(ref version, value);
}
private string summary;
public string Summary
{
get => summary;
set => SetProperty(ref summary, value);
}
}
- 有
ViewModel
,其中有IList<Package>
属性 和AsyncRelayCommand
调用进程,获取输出并更新 属性。
class MainWindowViewModel : ObservableObject
{
public AsyncRelayCommand StartProcessCommand { get; }
public MainWindowViewModel()
{
StartProcessCommand = new AsyncRelayCommand(StartProcess, CanStartProcess);
}
private async Task StartProcess()
{
//Start process, collect the output and set the PackageList property
}
private IList<Package> packagesList;
public IList<Package> PackagesList
{
get => packagesList;
set => SetProperty(ref packagesList, value);
}
}
- 然后有一个
View
绑定如下:
<ListView ItemsSource="{Binding PackagesList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}"/>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Version" DisplayMemberBinding="{Binding Version}" />
<GridViewColumn Header="Summary" DisplayMemberBinding="{Binding Summary}"/>
</GridView>
</ListView.View>
</ListView>
和调用 RelayCommand 的按钮(异步)。
这是我面临的问题
我想应用搜索 TextBox
来动态搜索 IList<Package>
的结果,为此我在 ViewModel
中创建了一个 SearchText
在 PropertyChanged
事件上更新 IList<Package>
属性。问题是我的 属性 正在改变,我想 不记得 每次都从过程中回忆它。
- 创建列表
- 搜索列表并将其呈现在视图中
- 如果我要删除我的 searchText 值,它仍然显示从点 1 开始的列表
实现此目标的最佳方法是什么?
到目前为止我已经到了,但只工作了一次,过滤列表但不返回到之前的列表:
public void SearchItem()
{
PackagesList = packagesList.Where(package => package.Id == SearchText).ToList();
}
private string? searchText;
public string? SearchText
{
get => searchText;
set
{
SetProperty(ref searchText, value);
SearchItem();
}
}
按照你的说法,你想在删除文本后显示所有数据? 如果是这样,你可以试试这个
public void SearchItem()
{
PackagesList = packagesList.Where(package => package.Id == SearchText || null == SearchText).ToList();
}
在 MainWindowViewModel
中创建另一个 属性 IList<Package>
并将其命名为 ResultList
private IList<Package> ResultList { get; set;} // Add Result list
private IList<Package> packagesList;
public IList<Package> PackagesList
{
get => packagesList;
set => SetProperty(ref packagesList, value);
}
改为将 ItemsSource 绑定设置为 ResultList
。
<ListView ItemsSource="{Binding ResultList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}"/>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Version" DisplayMemberBinding="{Binding Version}" />
<GridViewColumn Header="Summary" DisplayMemberBinding="{Binding Summary}"/>
</GridView>
</ListView.View>
</ListView>
任何时候您设置 PackagesList
,您也会设置 ResultList
。现在,当它进入搜索时,你会做一些这样的事情
public void SearchItem()
{
ResultList = packagesList.Where(package => package.Id == SearchText).ToList();
}