我以前从未使用过ReactiveExtensions。我在网上查找,但找不到适合我需求的方法。与我需要实现的目标相比,所有示例似乎都有点"过头"。
我有一个为我做所有事情的方法,所以我不需要返回值然后设置我的列表。我想要的只是在用户最终停止键入时执行该方法,而不是在用户键入时执行该方法。如何通过使用反应式扩展来实现这一点。
目前我有以下内容:
private string _searchText;
public String SearchText
{
get { return _searchText; }
set
{
_searchText = value;
MyMethod();
}
}
<textbox Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}"/>
除了在支持字段上设置值并引发更改通知外,您的属性不应执行其他操作。 所有其他逻辑都应该放在外面,通过可观察量监听这些更改通知。
在您的情况下,您希望仅在经过一定时间后侦听通知,因此您可以使用 IObservable.Throttle 运算符在转发通知之前等待特定的时间间隔。
因此,这可以是INotifyPropertyChanged的简单实现:
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
这是你应该如何写每个属性:
// Just check if value is different from the actual backing field.
// If and only if it is, set the backing field and raise the PropertyChanged event.
public string SearchText
{
get { return _SearchText; }
set
{
if (!EqualityComparer<string>.Default.Equals(_SearchText, value))
{
_SearchText = value;
NotifyPropertyChanged();
}
}
}
private string _SearchText;
第一个解决方案:视图模型中的限制:
// Transform the PropertyChanged event in an Observable
var changed = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
h => PropertyChanged += h,
h => PropertyChanged -= h);
// Transform the Observable to your need,
// filtering only when SearchText changes
changed.Where(x => x.EventArgs.PropertyName == nameof(SearchText))
// Wait 500 ms before forwarding the notification;
// if another char in inserted from the user beside this interval,
// the previous value is ignored
.Throttle(TimeSpan.FromMilliseconds(500))
// Necessary to avoid cross-thread Exceptions
.ObserveOn(Scheduler.CurrentThread)
// finally, subscribe your method:
.Subscribe(_ => MyMethod());
您可以将上面的代码放在任何合适的地方:在 ViewModel 的构造函数中,在Init()
方法中......
第二种解决方案:使用绑定的 Delay 属性
Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged, Delay=500}"
它有相同的结果。