/// <summary> /// コンストラクタ /// </summary> /// <param name="modelPool"></param> public StopWatchViewModel(IModelPool modelPool) { // モデルの取得 var model = modelPool.StopWatch; // モデルプロパティを取得 IsRunning = model.IsRunning; FormattedLaps = model.FormattedLaps; IsVisibleMills = model.IsVisibleMillis; // 表示用に20msec毎に間引き FormattedTime = model.FormattedTime .Throttle(TimeSpan.FromMilliseconds(20), Scheduler.Immediate) .ToReadOnlyReactiveProperty(); // アンダースコア:破棄。使用しないということ。 // https://ufcpp.net/study/csharp/datatype/declarationexpressions/#underscore // http://blog.xin9le.net/entry/2017/05/28/020129 // STOPされたら、最速/最遅 ラップを表示して LapActivityへ遷移 IsRunning.Where(x => !x). Subscribe(_ => { // Toastを表示させる Messenger.Send(new ShowToastMessage( $"最速ラップ:{model.FastestLaps}, 最遅ラップ:{model.WorstLaps}")); // LapActivityへ遷移させる Messenger.Send(new StartViewMessage(typeof(LapViewModel))); }) .AddTo(_subscriptions); // 開始 or 停止 CommandStartOrStop = new ReactiveCommand(); // いつでも実行可能 CommandStartOrStop.Subscribe(_ => { model.StartOrStop(); }) .AddTo(_subscriptions); // 経過時間の記録 CommandLap = IsRunning.ToReactiveCommand(); // 実行中(IsRunning = true)のみ記録可能 CommandLap.Subscribe(_ => { model.Lap(); }) .AddTo(_subscriptions); // ミリ秒以下表示切替 CommandToggleVisibleMillis = new ReactiveCommand(); // いつでも実行可能 CommandToggleVisibleMillis.Subscribe(_ => { model.ToggleVisibleMillis(); }) .AddTo(_subscriptions); }
} = new ReactiveCommand(); // いつでも実行可能 public MainViewModel(IModelPool modelPool) { var stopWatch = modelPool.StopWatch; // ■プロパティの実装 // StopWatchModel の各プロパティをそのまま公開してるだけ IsRunning = stopWatch.IsRunning; Laps = stopWatch.Laps; IsVisibleMillis = stopWatch.IsVisibleMillis; // 表示用にthrottleで20ms毎に間引き。View側でやってもよいかも。 Time = stopWatch.Time.Throttle(TimeSpan.FromMilliseconds(20), Scheduler.Immediate).ToReadOnlyReactiveProperty(); // ミリ秒以下表示有無に応じて、format書式文字列を切り替え(これはModelでやるべき?) TimeFormat = stopWatch.IsVisibleMillis.Select(x => x ? @"mm\:ss\.fff" : @"mm\:ss").ToReadOnlyReactiveProperty(); // STOP されたら、最速/最遅ラップを表示して、LapActivity へ遷移 IsRunning.Where(x => !x) .Subscribe(_ => { // Toast を表示させる Messenger.Send(new ShowToastMessage( $"最速ラップ:{stopWatch.FastestLap}, 最遅ラップ:{stopWatch.WorstLap}")); // FIXME 時間がformatされてない // LapActivity へ遷移させる Messenger.Send(new StartViewMessage(typeof(LapViewModel))); // ホントは LapViewModel を指定して画面遷移すべき }) .AddTo(_subscriptions); // ■コマンドの実装 // 開始 or 終了 CommandStartOrStop = new ReactiveCommand(); // いつでも実行可能 CommandStartOrStop.Subscribe(_ => { stopWatch.StartOrStop(); }) .AddTo(_subscriptions); // 経過時間の記録 CommandLap = IsRunning.ToReactiveCommand(); // 実行中のみ記録可能 CommandLap.Subscribe(_ => { stopWatch.Lap(); }) .AddTo(_subscriptions); // ミリ秒以下表示の切り替え CommandToggleVisibleMillis = new ReactiveCommand(); // いつでも実行可能 CommandToggleVisibleMillis.Subscribe(_ => { stopWatch.ToggleVisibleMillis(); }) .AddTo(_subscriptions); }
} = new ReactiveCommand(); // いつでも実行可能 public MainViewModel(INavigationService navigationService, IPageDialogService dialogService, IStopWatchModel stopWatch) { // ■プロパティの実装 // StopWatchModel の各プロパティをそのまま公開してるだけ IsRunning = stopWatch.IsRunning; FormattedLaps = stopWatch.FormattedLaps; IsVisibleMillis = stopWatch.IsVisibleMillis; // 表示用にthrottleで20ms毎に間引き。View側でやってもよいかも。 FormattedTime = stopWatch.FormattedTime //.Do(x=> Debug.WriteLine($"Throttled:{x}")) .ToReadOnlyReactiveProperty(); //// STOP されたら、最速/最遅ラップを表示して、LapActivity へ遷移 IsRunning.Buffer(2, 1).Where(x => x[0] && !x[1]) .Subscribe(async _ => { // Alert を表示させる await dialogService.DisplayAlertAsync( "Fastest/Worst Lap", $"Fastest:{stopWatch.FormattedFastestLap.Value}\n" + $"Worst:{stopWatch.FormattedWorstLap.Value}", "Close"); // LapActivity へ遷移させる await navigationService.NavigateAsync("LapPage"); }) .AddTo(_subscriptions); // ■コマンドの実装 // 開始 or 終了 StartOrStopCommand = new ReactiveCommand(); // いつでも実行可能 StartOrStopCommand.Subscribe(_ => { stopWatch.StartOrStop(); }); // 経過時間の記録 LapCommand = IsRunning.ToReactiveCommand(); // 実行中のみ記録可能 LapCommand.Subscribe(_ => { stopWatch.Lap(); }); // ミリ秒以下表示の切り替え ToggleVisibleMillisCommand = new ReactiveCommand(); // いつでも実行可能 ToggleVisibleMillisCommand.Subscribe(_ => { stopWatch.ToggleVisibleMillis(); }); }
public MainViewModel(INavigationService navigationService, IPageDialogService dialogService, LocationUseCase locationUseCase) { // ■プロパティの実装 // LocationUseCase の各プロパティを必要なら加工して公開 IsRunning = locationUseCase.IsRunning.ToReadOnlyReactiveProperty(); // Location の時刻をフォーマットして公開 FormattedTime = locationUseCase.Location .Select(l => l.Time.ToString("HH:mm:ss")) .ToReadOnlyReactiveProperty(); // Location の緯度を度分秒または度にフォーマットして公開 FormattedLatitude = IsDmsFormat.CombineLatest( locationUseCase.Location.Select(l => l.Latitude), (isDms, lat) => lat.Format(isDms)) .ToReadOnlyReactiveProperty(); // Location の経度を度分秒または度にフォーマットして公開 FormattedLongitude = IsDmsFormat.CombineLatest( locationUseCase.Location.Select(l => l.Longitude), (isDms, lon) => lon.Format(isDms)) .ToReadOnlyReactiveProperty(); // 記録されたレコード群を件数として公開 RecordCount = locationUseCase.Records .ToCollectionChanged() .Select(_ => locationUseCase.Records.Count) .ToReadOnlyReactiveProperty(); //// STOP されたら、最も精度のよい位置情報を表示して、RecordsPage へ遷移 IsRunning .Buffer(2, 1) .Where(x => x[0] && !x[1]) .Subscribe(async _ => { // 最も精度のよい緯度経度を得る // 返値がメソッドは、その時点の情報でしかない(Reactiveではない)ので注意すること var bestLocation = locationUseCase.GetBestLocation(); var message = bestLocation.HasValue ? $"{bestLocation.Value.Latitude.Format(IsDmsFormat.Value)}/" + $"{bestLocation.Value.Longitude.Format(IsDmsFormat.Value)} です。" : "記録されてません"; //// Alert を表示させる await dialogService.DisplayAlertAsync("最も精度の良い位置は", message, "Close"); // RecordPage へ遷移させる await navigationService.NavigateAsync("RecordsPage"); }); // ■コマンドの実装 // 開始 or 終了 StartOrStopCommand = new ReactiveCommand(); // いつでも実行可能 StartOrStopCommand.Subscribe(_ => { locationUseCase.StartOrStop(); }); // 位置情報の記録 RecordCommand = IsRunning.ToReactiveCommand(); // 実行中のみ記録可能 RecordCommand.Subscribe(_ => { locationUseCase.Record(); }); }
public MainViewModel() { // ファイルから読む体で userDict.Add("111", new UserModel("111", "社会人P") { Color = Colors.LightGreen }); userDict.Add("222", new UserModel("222", "八百屋")); Comments = model.Comments.ToReadOnlyReactiveCollection(comment => { if (!userDict.TryGetValue(comment.ID, out var user)) { user = new UserModel(comment.ID); userDict.Add(user.ID, user); } return(new CommentViewModel(comment, user)); }).AddTo(disposable); #region Command NameChangeCommand.Subscribe(obj => { var menuItem = obj as MenuItem; var comment = menuItem.DataContext as CommentViewModel; var ib = new InputBox { DataContext = comment, Text = comment.Name.Value, }; if (ib.ShowDialog() == true) { comment.Name.Value = ib.Text; } }); ColorChangeCommand.Subscribe(obj => { var menuItem = obj as MenuItem; var comment = menuItem.DataContext as CommentViewModel; comment.Color.Value = (Color)menuItem.Tag; }); ConnectCommand = IsRunning.Select(x => !x).ToAsyncReactiveCommand(); ConnectCommand.Subscribe(async _ => { await model.ConnectAsync("lv1234567"); IsRunning.Value = true; }).AddTo(disposable); DisconnectCommand = IsRunning.ToReactiveCommand(); DisconnectCommand.Subscribe(_ => { model.Disconnect(); IsRunning.Value = false; }).AddTo(disposable); #endregion ConnectCommand.Execute(); }