使用 IReactiveDerivedList 的正确方法是用户在其中键入过滤条件
Correct way to use IReactiveDerivedList as a user types a filter term in
我在 ReactiveList<string>
中有一个字符串的根列表
private ReactiveList<string> Items { get; set; }
和派生列表
private IReactiveDerivedList<string> _FilteredItems;
public IReactiveDerivedList<string> FilteredItems{ get => _FilteredItems; set => this.RaiseAndSetIfChanged(ref _FilteredItems, value); }
我还有一个过滤条件,当用户键入 TextBox
时会发生变化
private string _FilterTerm;
public string FilterTerm { get => _FilterTerm; set => this.RaiseAndSetIfChanged(ref _FilterTerm, value); }
最后,我在我的构造函数中使用以下内容,每次 FilterTerm
更改时 重新创建 派生列表
this.WhenAnyValue(This => This.FilterTerm).Where(filterTerm => filterTerm != null).Subscribe((filterTerm) =>
{
FilteredItems = Items.CreateDerivedCollection(x => x, x => x.Contains(FilterTerm));
});
...我这样做是否正确,或者是否有更好的方法,因为这感觉有点像 'I could just create a new ReactiveList
each time, why bother with the IReactiveDerivedList
'?
更新
我找到了下面的例子,它几乎对我有用,https://janhannemann.wordpress.com/2016/10/18/reactiveui-goodies-ireactivederivedlist-filtering-2/,但它要求我向我的 ViewModel 添加一个 IsFiltered
属性,但在这种情况下,我没有使用 ViewModel,我只是使用 string
!
如我评论中所述。 ReactiveUI 框架弃用了 ReactiveList,取而代之的是 DynamicData https://reactiveui.net/docs/handbook/collections/
如果您要在 DynamicData 中实现此目的,您将执行以下操作:
using System.Collections.ObjectModel;
using DynamicData;
public class FilteringClass
{
private readonly ReadOnlyObservableCollection<string> _filteredItems;
private readonly SourceList<string> _items = new SourceList<string>();
private string _filterTerm;
public FilteringClass(IEnumerable<string> items)
{
var filterTermChanged = this.WhenAnyValue(x => x.FilterTerm);
_items.AddRange(items);
_items.Connect()
// This will update your output list whenever FilterTerm changes.
.AutoRefreshOnObservable(_ => filterTermChanged)
// This is similar to a Where() statement.
.Filter(x => FilterTerm == null || x.Contains(FilterTerm))
// SourceList is thread safe, this will make your output list only be updated on the main thread.
.ObserveOn(RxApp.MainThreadScheduler)
// This will make the FilteredItem's be updated with our data.
.Bind(out _filteredItems)
// This is a observable, so Subscribe to start the goodness.
.Subscribe();
}
public string FilterTerm
{
get => _filterTerm;
set => RaiseAndSetIfChanged(ref _filterTerm, value);
}
public ReadOnlyObservableCollection<string> FilteredItems => _filteredItems;
}
我在 ReactiveList<string>
private ReactiveList<string> Items { get; set; }
和派生列表
private IReactiveDerivedList<string> _FilteredItems;
public IReactiveDerivedList<string> FilteredItems{ get => _FilteredItems; set => this.RaiseAndSetIfChanged(ref _FilteredItems, value); }
我还有一个过滤条件,当用户键入 TextBox
private string _FilterTerm;
public string FilterTerm { get => _FilterTerm; set => this.RaiseAndSetIfChanged(ref _FilterTerm, value); }
最后,我在我的构造函数中使用以下内容,每次 FilterTerm
更改时 重新创建 派生列表
this.WhenAnyValue(This => This.FilterTerm).Where(filterTerm => filterTerm != null).Subscribe((filterTerm) =>
{
FilteredItems = Items.CreateDerivedCollection(x => x, x => x.Contains(FilterTerm));
});
...我这样做是否正确,或者是否有更好的方法,因为这感觉有点像 'I could just create a new ReactiveList
each time, why bother with the IReactiveDerivedList
'?
更新
我找到了下面的例子,它几乎对我有用,https://janhannemann.wordpress.com/2016/10/18/reactiveui-goodies-ireactivederivedlist-filtering-2/,但它要求我向我的 ViewModel 添加一个 IsFiltered
属性,但在这种情况下,我没有使用 ViewModel,我只是使用 string
!
如我评论中所述。 ReactiveUI 框架弃用了 ReactiveList,取而代之的是 DynamicData https://reactiveui.net/docs/handbook/collections/
如果您要在 DynamicData 中实现此目的,您将执行以下操作:
using System.Collections.ObjectModel;
using DynamicData;
public class FilteringClass
{
private readonly ReadOnlyObservableCollection<string> _filteredItems;
private readonly SourceList<string> _items = new SourceList<string>();
private string _filterTerm;
public FilteringClass(IEnumerable<string> items)
{
var filterTermChanged = this.WhenAnyValue(x => x.FilterTerm);
_items.AddRange(items);
_items.Connect()
// This will update your output list whenever FilterTerm changes.
.AutoRefreshOnObservable(_ => filterTermChanged)
// This is similar to a Where() statement.
.Filter(x => FilterTerm == null || x.Contains(FilterTerm))
// SourceList is thread safe, this will make your output list only be updated on the main thread.
.ObserveOn(RxApp.MainThreadScheduler)
// This will make the FilteredItem's be updated with our data.
.Bind(out _filteredItems)
// This is a observable, so Subscribe to start the goodness.
.Subscribe();
}
public string FilterTerm
{
get => _filterTerm;
set => RaiseAndSetIfChanged(ref _filterTerm, value);
}
public ReadOnlyObservableCollection<string> FilteredItems => _filteredItems;
}