如何将搜索应用于 MVVM (WPF) 中的列表,而无需每次都调用列表值?

Posted

技术标签:

【中文标题】如何将搜索应用于 MVVM (WPF) 中的列表,而无需每次都调用列表值?【英文标题】:How to apply search to the list in the MVVM (WPF) without recalling the list values every time? 【发布时间】:2022-01-14 07:14:34 【问题描述】:

首先,我是 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);
        

    ViewModelIList<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&lt;Package&gt; 的结果,为此我在ViewModel 中创建了一个SearchText,它更新了@987654336 上的IList&lt;Package&gt; 属性@ 事件。问题是我的财产正在发生变化,我想不记得每次都从这个过程中。

    创建列表 搜索列表并将其显示在视图中 如果我删除了我的 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();
            
            
        

【问题讨论】:

docs.microsoft.com/en-us/dotnet/desktop/wpf/data/… 请尽量减少问题。 ***.com/help/minimal-reproducible-example 创建一个IList&lt;Package&gt; 并将其命名为ResultList 或任何名称。将您的ItemsSource 绑定设置为ResultList。任何时候你设置PackagesList,你也设置ResultList。现在当它进入搜索时,你会做这种ResultList = packagesList.Where(package =&gt; package.Id == SearchText).ToList(); @Jeffery 谢谢你的建议。这样就解决了问题! @user8909887 我将其发布为答案。将其标记为帮助他人的答案 【参考方案1】:

MainWindowViewModel 中创建另一个属性IList&lt;Package&gt; 并将其命名为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();

【讨论】:

【参考方案2】:

根据您的说法,您想在删除文本后显示所有数据吗? 如果是这样,你可以试试这个

public void SearchItem()
   
    PackagesList = packagesList.Where(package => package.Id == SearchText || null == SearchText).ToList();

【讨论】:

以上是关于如何将搜索应用于 MVVM (WPF) 中的列表,而无需每次都调用列表值?的主要内容,如果未能解决你的问题,请参考以下文章

使用 MVVM 从 WPF ListView 项触发双击事件

WPF MVVM更新列表框

如何在 MVVM 中的 UserControl 之间进行通信 - WPF 应用程序

将 WPF ValidationRule 的状态传递给 MVVM 中的视图模型

如何在 WPF / MVVM 中对绑定到相同实例的两个列表视图进行不同选择

如何使用 MVVM 模式“禁用”WPF 中的按钮?