反应式扩展即时搜索 WPF/MVVM [英] Reactive Extensions Instant Search for WPF/MVVM
问题描述
我想实现一个文本框,当您输入时,结果会立即出现在另一个列表框中.我一直在寻找 Reactive Extensions (Rx) 的示例,我发现的所有示例都使用 Observable.FromEventPattern()
和 TextBox 的 TextChanged
事件:>
我将 WPF 与 MVVM 结合使用,因此我无法直接访问 TextBox 或其事件.
我还偶然发现了这个答案,它显示了 Observable.FromEventPattern()
可用于 MVVM 设置,但我希望有比捕获每个 PropertyChanged
事件更好的方法.
Observable.FromEventPattern()
有什么好的替代方案可以很好地与 WPF/MVVM 配合使用?
使用 ReactiveUI 解决了这个问题.
该解决方案基于 博客文章 在 ReactiveUI,但是那里的代码有点
这是来自该解决方案的 ViewModel.SearchText
绑定到用户键入查询的视图中的 TextBox
,而 SearchResults
绑定到 ListBox
> 显示结果.
使用系统;使用 System.Collections.Generic;使用 System.Linq;使用 System.Text;使用 System.Collections.ObjectModel;使用 System.Threading.Tasks;使用 System.ComponentModel;使用 System.Reactive.Linq;使用 System.Windows.Input;使用 ReactiveUI;命名空间 ReactiveExtensionsSearch{公共类 MainWindowViewModel : ReactiveObject{私有字符串[] _repository = 新字符串[]{马里奥"、玛丽亚"、吉吉"、杰克"、詹姆斯"、杰瑞米"};private ObservableAsPropertyHelper>_搜索结果;私人字符串_searchText;私人 ICommand _executeSearchCommand;公共字符串搜索文本{得到{返回_searchText;}放{this.RaiseAndSetIfChanged(ref _searchText, value);}}公共 ObservableCollection;搜索结果{得到{返回_searchResults.Value;}}公共 MainWindowViewModel(){var executeSearchCommand = new ReactiveCommand();var 结果 = executeSearchCommand.RegisterAsyncFunction(s => { return ExecuteSearch(s as string); });_executeSearchCommand = 执行搜索命令;this.ObservableForProperty("SearchText").Throttle(TimeSpan.FromMilliseconds(800)).Select(x => x.Value).DistinctUntilChanged().Where(x => !string.IsNullOrWhiteSpace(x)).Subscribe(_executeSearchCommand.Execute);_searchResults = new ObservableAsPropertyHelper>(results, _ => raisePropertyChanged("SearchResults"));}私有 ObservableCollection执行搜索(字符串搜索文本){var q = from s in _repository where s.ToLower().StartsWith(searchText.ToLower()) select s;var 结果 = new ObservableCollection(q);返回结果;}}}
I would like to implement a TextBox where, as you type, results appear instantly in another ListBox. I've been looking for examples with Reactive Extensions (Rx), and all of the ones I found use Observable.FromEventPattern()
together with the TextBox's TextChanged
event:
- Implementing simple instant search with Rx (Reactive Extensions) (this is actually WinForms)
- An Rx-Enabled WPF AutoComplete TextBox - Part 1/2
- Search on TextChanged with Reactive Extensions
I'm using WPF with MVVM so I can't exactly access the TextBox or its events directly.
I've also stumbled upon this answer which shows how Observable.FromEventPattern()
can be used in an MVVM setting, but I was hoping for something better than capturing every single PropertyChanged
event.
What is a good alternative to Observable.FromEventPattern()
that can work nicely with WPF/MVVM?
Got this working with ReactiveUI.
The solution is based on a blog post at ReactiveUI, but the code there is a little bit out of date. I am hosting the solution on BitBucket for ease of access. It uses ReactiveUI 5.5.1.
This is the ViewModel from that solution. SearchText
is bound to a TextBox
in the View where the user types his query, while SearchResults
is bound to a ListBox
displaying the results.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Reactive.Linq;
using System.Windows.Input;
using ReactiveUI;
namespace ReactiveExtensionsSearch
{
public class MainWindowViewModel : ReactiveObject
{
private string[] _repository = new string[]
{ "Mario", "Maria", "Gigi", "Jack", "James", "Jeremy" };
private ObservableAsPropertyHelper<ObservableCollection<string>> _searchResults;
private string _searchText;
private ICommand _executeSearchCommand;
public string SearchText
{
get
{
return _searchText;
}
set
{
this.RaiseAndSetIfChanged(ref _searchText, value);
}
}
public ObservableCollection<string> SearchResults
{
get
{
return _searchResults.Value;
}
}
public MainWindowViewModel()
{
var executeSearchCommand = new ReactiveCommand();
var results = executeSearchCommand.RegisterAsyncFunction(s => { return ExecuteSearch(s as string); });
_executeSearchCommand = executeSearchCommand;
this.ObservableForProperty<MainWindowViewModel, string>("SearchText")
.Throttle(TimeSpan.FromMilliseconds(800))
.Select(x => x.Value)
.DistinctUntilChanged()
.Where(x => !string.IsNullOrWhiteSpace(x))
.Subscribe(_executeSearchCommand.Execute);
_searchResults = new ObservableAsPropertyHelper<ObservableCollection<string>>(results, _ => raisePropertyChanged("SearchResults"));
}
private ObservableCollection<string> ExecuteSearch(string searchText)
{
var q = from s in _repository where s.ToLower().StartsWith(searchText.ToLower()) select s;
var results = new ObservableCollection<string>(q);
return results;
}
}
}
这篇关于反应式扩展即时搜索 WPF/MVVM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!