NuGet Gallery | ReactiveProperty 2.0.0-pre4
さっきpre3リリースしましたが、バージョンアップです。
メソッド名の変更
先ほど追加したEventToReactiveCommand用のReactiveConverterとDelegateConverterクラスのConvertメソッド名をConvertToに変更しました。Convertのままだと、実装しているインターフェースのConvertメソッドとかぶってオーバーライド出来ないことがあったので…。
EventToReactiveのObsolate化
この後紹介する機能とかぶるので非推奨にしました。
EventToReactivePropertyの追加
EventToReactiveCommandのReactiveProperty版です。
以下のようなConverterを定義して。
public class EventToReactivePropertyViewModel { // binding from UI, event direct bind public ReactiveProperty<Unit> MouseDown { get; private set; } // binding from UI, event with converter public ReactiveProperty<Tuple<int, int>> MouseMove { get; private set; } // binding from UI, IgnoreEventArgs = true public ReactiveProperty<Unit> MouseEnter { get; private set; } public ReactiveProperty<string> CurrentPoint { get; private set; } public ReactiveProperty<string> Entered { get; private set; } public ReactiveProperty<string> AlertMessage { get; private set; } public EventToReactivePropertyViewModel() { // mode off RaiseLatestValueOnSubscribe, because initialValue is null. // mode off DistinctUntilChanged, because if Unit no send any values. var none = ReactivePropertyMode.None; MouseMove = new ReactiveProperty<Tuple<int, int>>(mode: none); MouseDown = new ReactiveProperty<Unit>(mode: none); MouseEnter = new ReactiveProperty<Unit>(mode: none); CurrentPoint = MouseMove .Select(p => string.Format("X:{0} Y:{1}", p.Item1, p.Item2)) .ToReactiveProperty(); Entered = MouseEnter .Select(_ => Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1))) .Switch() .Select(x => "entered:" + x + "sec") .ToReactiveProperty(); this.AlertMessage = MouseDown.Select(_ => "MouseDown!").ToReactiveProperty(mode: none); } } // EventToReactiveProperty converter. // Converter/IgnoreEventArgs is useful for unit testings. // For example, MouseMovoe.Value = new Point(10, 10) is simulate MouseMove // MouseEnter.Value = new Unit() is simulate raise MouseEnter event. public class MouseEventToPointConverter : ReactiveConverter<dynamic, Tuple<int, int>> { protected override IObservable<Tuple<int, int>> OnConvert(IObservable<dynamic> source) { return source .Select(x => x.GetPosition(null)) .Select(x => Tuple.Create((int)x.X, (int)x.Y)); } }
EventTriggerなどと組み合わせて以下のように使います。
<Grid> <!-- Use Blend SDK's Interaction Trigger --> <!-- Event binding to ReactiveProperty --> <i:Interaction.Triggers> <i:EventTrigger EventName="MouseMove"> <!-- ConvertBack function is Func<object, object>--> <r:EventToReactiveProperty ReactiveProperty="{Binding MouseMove}"> <vm:MouseEventToPointConverter/> </r:EventToReactiveProperty> </i:EventTrigger> <i:EventTrigger EventName="MouseDown"> <!-- direct event bind --> <r:EventToReactiveProperty ReactiveProperty="{Binding MouseDown}" IgnoreEventArgs="True" /> </i:EventTrigger> <i:EventTrigger EventName="MouseEnter"> <!-- IgnoreEventArgs = true send Unit --> <r:EventToReactiveProperty ReactiveProperty="{Binding MouseEnter}" IgnoreEventArgs="true" /> </i:EventTrigger> </i:Interaction.Triggers> <TextBlock Text="{Binding CurrentPoint.Value}" /> <TextBlock Text="{Binding Entered.Value}" Margin="0,100,0,0" /> </Grid>