Eni*_*ity 0 .net c# silverlight system.reactive
我正在尝试从Silverlight应用程序中删除更多的传统事件处理程序,转而使用大量Rx查询来提供更好,更易于管理的行为抽象.
我需要解决的问题,但不能按照我想要的方式破解它,是让搜索屏幕的行为正常工作.这是非常标准的东西.这是它应该如何表现:
我有这些observable(通过标准事件的一些扩展方法创建)来使用:
IObservable<IEvent<TextChangedEventArgs>> textBox.TextChangedObservable()
IObservable<IEvent<RoutedEventArgs>> button.ClickObservable()
IObservable<IEvent<LoadingDataEventArgs>> dataSource.LoadingDataObservable()
IObservable<IEvent<LoadedDataEventArgs>> dataSource.LoadedDataObservable()
Run Code Online (Sandbox Code Playgroud)
我现在有这些查询:
IObservable<bool> dataSourceIsBusy =
dataSource.LoadingDataObservable().Select(x => true)
.Merge(dataSource.LoadedDataObservable().Select(x => false));
IObservable<string> textBoxText =
from x in textBox.TextChangedObservable()
select textBox.Text.Trim();
IObservable<bool> textBoxTextIsValid =
from text in textBoxText
let isValid = !String.IsNullOrEmpty(text)
select isValid;
IObservable<string> searchTextReady =
from x in button.ClickObservable()
select textBox.Text.Trim();
Run Code Online (Sandbox Code Playgroud)
然后这些订阅连接起来:
buttonIsEnabled.Subscribe(x => button.IsEnabled = x);
dataSourceIsBusy.Subscribe(x => textBox.IsEnabled = !x);
searchTextReady.Subscribe(x => this.ExecuteSearch(x));
Run Code Online (Sandbox Code Playgroud)
(我确实保留了对Subscribe方法返回的一次性用法的引用.我已经.ObserveOnDispatcher()添加到每个observable以确保代码在UI线程上运行.)
现在,虽然这有效,但有一件事让我烦恼.searchTextReady调用中的select语句textBox.Text.Trim()获取当前修剪的搜索文本,但我已经在textBoxTextobservable中完成了此操作.我真的不想重复自己,所以我想创建一个结合了这些可观察量的查询,这就是我失败的地方.
当我尝试以下查询时,我会重新调用以执行搜索:
IObservable<string> searchTextReady =
from text in textBoxText
from x in button.ClickObservable()
select text;
Run Code Online (Sandbox Code Playgroud)
以下查询似乎适用于第一个查询,但每次我更改文本框中的文本后,搜索将自动执行而不单击搜索按钮:
IObservable<string> searchTextReady =
from text in button.ClickObservable()
.CombineLatest(textBoxText, (c, t) => t)
select text;
Run Code Online (Sandbox Code Playgroud)
以下查询要求在单击搜索按钮后再进行文本更改,然后再次无法运行:
IObservable<string> searchTextReady =
from text in textBoxText
.SkipUntil(button.ClickObservable())
.TakeUntil(dataSource.LoadingDataObservable())
select text;
Run Code Online (Sandbox Code Playgroud)
我有什么想法可以使这项工作?
这些东西本身很棘手,所以我最终编写了一个MV-VM + Rx库来帮助我 - 事实证明,使用这个库,这项任务非常简单; 这是整个代码,我的博客解释了这些类如何工作的更多信息:
public class TextSearchViewModel
{
public TextSearchViewModel
{
// If there is no text (or whitespace only) then the search button is disabled.
var isSearchEnabled = this.ObservableForProperty(x => x.SearchText)
.Select(x => !String.IsNullOrWhitespace(x.Value));
// Create an ICommand that represents the Search button
// Setting 1 at a time will make sure the Search button disables while search is running
DoSearch = new ReactiveAsyncCommand(isSearchEnabled, 1/*at a time*/);
// When the user clicks search the text box and the search button are both disabled.
var textBoxEnabled = DoSearch.ItemsInflight
.Select(x => x == 0);
// Always update the "TextboxEnabled" property with the latest textBoxEnabled IObservable
_TextboxEnabled = this.ObservableToProperty(textBoxEnabled,
x => x.TextboxEnabled, true);
// Register our search function to run in a background thread - for each click of the Search
// button, the searchResults IObservable will produce a new OnNext item
IObservable<IEnumerable<MyResult>> searchResults = DoSearch.RegisterAsyncFunction(textboxText => {
var client = new MySearchClient();
return client.DoSearch((string)textboxText);
});
// Always update the SearchResults property with the latest item from the searchResults observable
_SearchResults = this.ObservableToProperty(searchResults, x => x.SearchResults);
}
// Create a standard INotifyPropertyChanged property
string _SearchText;
public string SearchText {
get { return _SearchText; }
set { this.RaiseAndSetIfChanged(x => x.SearchText, value); }
}
// This is a property who will be updated with the results of an observable
ObservableAsPropertyHelper<bool> _TextboxEnabled;
public bool TextboxEnabled {
get { return _TextboxEnabled.Value; }
}
// This is an ICommand built to do tasks in the background
public ReactiveAsyncCommand DoSearch { get; protected set; }
// This is a property who will be updated with the results of an observable
ObservableAsPropertyHelper<IEnumerable<MyResult>> _SearchResults;
public IEnumerable<MyResult> SearchResults {
get { return _SearchResults.Value; }
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1459 次 |
| 最近记录: |