Я пытаюсь удалить более традиционные обработчики событий из приложения Silverlight в пользу использования ряда запросов Rx для обеспечения лучшей, более простой в управлении, поведенческой абстракции.
Проблема, которая мне нужнарешить, но не могу взломать его так, как я хочу, чтобы заставить работать экран поиска.Это довольно стандартные вещи.Вот как он должен себя вести:
- У меня есть текстовое поле , где пользователь может ввести текст поиска .
- Если естьЕсли нет текста (или только пробелы) , тогда кнопка поиска будет отключена .
- Когда есть текст без пробелов , тогда кнопка поиска включена .
- Когда пользователь нажимает кнопку поиска текстовое поле и кнопка поиска оба отключены .
- Когда возвращаются результаты текстовое поле и кнопка поиска оба включены .
У меня есть эти наблюдаемые (созданные с помощью некоторых методов расширения для стандартных событий) для работы с:
IObservable<IEvent<TextChangedEventArgs>> textBox.TextChangedObservable()
IObservable<IEvent<RoutedEventArgs>> button.ClickObservable()
IObservable<IEvent<LoadingDataEventArgs>> dataSource.LoadingDataObservable()
IObservable<IEvent<LoadedDataEventArgs>> dataSource.LoadedDataObservable()
У меня есть эти запросы, которые работают в данный момент:
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();
И затем эти подписки, чтобы связать все это:
buttonIsEnabled.Subscribe(x => button.IsEnabled = x);
dataSourceIsBusy.Subscribe(x => textBox.IsEnabled = !x);
searchTextReady.Subscribe(x => this.ExecuteSearch(x));
(я сохраняю ссылки на одноразовые товары, возвращаемые Subscribe
методов.Я добавил .ObserveOnDispatcher()
к каждой наблюдаемой, чтобы обеспечить выполнение кода в потоке пользовательского интерфейса.)
Теперь, пока это работает, есть одна вещь, которая меня беспокоит.Оператор select в searchTextReady
вызывает textBox.Text.Trim()
, чтобы получить текущий обрезанный текст поиска, но я уже сделал это в наблюдаемой textBoxText
.Я действительно не хочу повторяться, поэтому я хотел бы создать запрос, который объединяет эти наблюдаемые, и вот где я терплю неудачу.
Когда я пытаюсь выполнить следующий запрос, я получаю повторные входящие вызовы для выполненияпоиск:
IObservable<string> searchTextReady =
from text in textBoxText
from x in button.ClickObservable()
select text;
Следующий запрос, кажется, работает для первого запроса, но затем каждый раз, когда я изменяю текст в текстовом поле, после этого поиск автоматически выполняется без нажатия кнопки поиска:
IObservable<string> searchTextReady =
from text in button.ClickObservable()
.CombineLatest(textBoxText, (c, t) => t)
select text;
Следующий запрос требует, чтобы после нажатия кнопки поиска происходило дальнейшее изменение текста, а затем он снова не запускался:
IObservable<string> searchTextReady =
from text in textBoxText
.SkipUntil(button.ClickObservable())
.TakeUntil(dataSource.LoadingDataObservable())
select text;
Есть идеи, как мне это сделать?