ReactiveUI: Rx + MVVM

17
Reactive UI Reactive Extensions + MVVM

Transcript of ReactiveUI: Rx + MVVM

Page 1: ReactiveUI: Rx + MVVM

Reactive UIReactive Extensions + MVVM

Page 2: ReactiveUI: Rx + MVVM
Page 3: ReactiveUI: Rx + MVVM

Rx.NETpublic interface IObservable<out T>{ IDisposable Subscribe(IObserver<T> observer);}

public interface IObserver<in T>{ void OnNext(T value); void OnError(Exception error); void OnCompleted();}

Page 4: ReactiveUI: Rx + MVVM
Page 5: ReactiveUI: Rx + MVVM

WP8

WinRT

Xamarin.Android

Xamarin.Touch

Xamarin.Mac

WPF

WinForms

Page 6: ReactiveUI: Rx + MVVM

Reactive Extensions + MVVMIObservable и LINQ +

INPC, INCCTextBox.TextChanged, ManipulationStartedEventетц.изменения значения BindingICommand вызовы, CanExecuteChangedFrame.Navigated, App.IsResuming етц.тестируемый параллелизм (concurrency)

Page 7: ReactiveUI: Rx + MVVM

ReactiveObjectpublic class VM : ReactiveObject { public VM() { this.WhenAnyValue(x => x.Name) .Select(x => x.Split( ' ')[0]) .ToProperty( this, x => x.FirstName); }

public string FirstName {get; private set;}}

Page 8: ReactiveUI: Rx + MVVM

Декларативный стильсвойство FirstName это подстрока Name до пробела

свойство BackgroundBrush это свойства Red, Green, Blue, объединенные в объект

Color, трансформированный в SolidColorBrush

Кнопка Login может быть нажата если свойства пароль и подтверждение пароля

непусты и совпадают

Page 9: ReactiveUI: Rx + MVVM

Output Propertiesthis.WhenAny(x => x.Red, x => x.Green, x => x.Blue, (r, g, b) => Color.FromRgb(r.Value, g.Value, b.Value)) .Select(color => new SolidColorBrush(color)) .ToProperty(this, x => x.BackgroundBrush);

public SolidColorBrush BackgroundBrush {get; private set;}

Page 10: ReactiveUI: Rx + MVVM

Eventsпример AutoComplete сценария

var searchTerms = txt.Events().TextChanged .Select(_ => txt.Text) .Where(term => term.Length > 3) .Throttle(TimeSpan.FromSeconds( 1)) .DistinctUntilChanged();

var searchResults = from term in searchTerms from words in _service.Search(term).TakeUntil(searchTerms) select words;

searchResults.ObserveOnDispatcher() .Subscribe(words => itemsControl.ItemsSource = words)

Page 11: ReactiveUI: Rx + MVVM

CommandsCanExecute via IObservable

var commandCanExecute = new Subject<bool>(); var command = new ReactiveCommand(commandCanExecute);

commandCanExecute.OnNext(false); command.CanExecute(null); >>> false

commandCanExecute.OnNext(true); command.CanExecute(null); >>> true</bool>

Page 12: ReactiveUI: Rx + MVVM

Async action per Command executeLoadUsersAndAvatars = new ReactiveCommand();

var usersAndAvatarResults = LoadUsersAndAvatars.RegisterAsyncTask(async _ => { var users = await LoadUsers();

foreach(var u in users) { u.Avatar = await LoadAvatar(u.Id); }

return users;});

usersAndAvatarResults.ToProperty(this, x => x.Users, ref users);

Page 13: ReactiveUI: Rx + MVVM

Bindings in code-behind

C# более экспрессивен, нежели XAMLthis.OneWayBind(ViewModel, x => x.Name, x => x.Name.Text);this.Bind(ViewModel, x => x.Name, x => x.Name.Text);// Bind the OK command to the buttonthis.BindCommand(ViewModel, x => x.OkCommand, x => x.OkButton);// Bind the OK command to when the user presses a keythis.BindCommand(ViewModel, x => x.OkCommand, x => x.RootView, "KeyUp");

Page 14: ReactiveUI: Rx + MVVM

INCC, ReactiveListIObservable => (selector, filter, orderer) => INCCthis.Feeds = feedModels.CreateCollection() .CreateDerivedCollection( CreateViewModel, model => model.LatestPublished > TimeBorder, FreshFirstOrderer);

Page 15: ReactiveUI: Rx + MVVM

ISchedulerВ Rx все асинхронные действия происходят с

помощью ISchedulervar initialDate = DateTime.Now;//simulate some cold data before ViewModel creation (and subscription)testPodcastsSubj.OnNext(new TestPodcastItem(1, initialDate.AddDays(1)));testPodcastsSubj.OnNext(new TestPodcastItem(2, initialDate.AddDays(2)));

var model = new FeedViewModel("TestFeed", testPodcasts);

Assert.AreEqual(2, ((TestPodcastItem)model.LastFeedItem).Id);Assert.AreEqual(2, model.Items.Count);

testPodcastsSubj.OnNext(new TestPodcastItem(3, initialDate.AddDays(3)));_virtualScheduler.AdvanceBy(TimeSpan.FromSeconds(1));

Assert.AreEqual(3, ((TestPodcastItem)model.LastFeedItem).Id);

Page 16: ReactiveUI: Rx + MVVM

Спасибо за внимание!Сабж: ReactieUI его автор: Паша Betts

и я, Стас Шуша

https://github.com/reactiveui

https://github.com/paulcbettsViber: +375298745697

Page 17: ReactiveUI: Rx + MVVM