Xamarin 版 SimpleTimer も完成間近
タイマー開始・一時停止・停止の処理を ViewModel の Command で追加してみました
#region Privates /// <summary> /// 元の値 /// </summary> private TimeSpan originValue; /// <summary> /// 元の最大値 /// </summary> private double originMaxSeconds; /// <summary> /// タイマー開始時経過ミリ秒 /// </summary> private int startTime; /// <summary> /// 排他制御オブジェクト /// </summary> private static readonly object LockObject = new object(); #endregion //Privates /// <summary> /// コンストラクタ /// </summary> public TopPageViewModel() { this.IsTimerStarted = false; this.IsEnableStop = false; this.timerValue = TimeSpan.FromMinutes(5); this.MaxSeconds = 3 * 60 * 60; this.originMaxSeconds = this.MaxSeconds; this.stopCommand = new Command(this.StopTimer); } /// <summary> /// タイマー開始フラグ の変更後の処理 /// </summary> private void OnIsTimerStartedChanged() { this.IsEnableStart = !this.isTimerStarted || this.isTimerPaused; this.IsEnablePause = this.isTimerStarted && !this.isTimerPaused; this.IsEnableStop = this.isTimerStarted; } /// <summary> /// タイマー一時停止フラグ の変更後の処理 /// </summary> private void OnIsTimerPausedChanged() { this.IsEnableStart = !this.isTimerStarted || this.isTimerPaused; this.IsEnablePause = this.isTimerStarted && !this.isTimerPaused; } #region TimerValue:タイマー残り秒数 プロパティ /// <summary> /// タイマー残り秒数 /// </summary> private TimeSpan timerValue; /// <summary> /// タイマー残り秒数 の取得および設定 /// </summary> public TimeSpan TimerValue { get { return this.timerValue; } set { this.SetProperty<TimeSpan>(ref this.timerValue, value); } } #endregion //TimerValue:タイマー残り秒数 プロパティ #region MaxSeconds:タイマー設定秒数 プロパティ /// <summary> /// タイマー設定秒数 /// </summary> private double maxSeconds; /// <summary> /// タイマー設定秒数 の取得および設定 /// </summary> public double MaxSeconds { get { return this.maxSeconds; } set { this.SetProperty<double>(ref this.maxSeconds, value); } } #endregion //MaxSeconds:タイマー設定秒数 プロパティ #region IsTimerPaused:タイマー一時停止フラグ プロパティ /// <summary> /// タイマー一時停止フラグ /// </summary> private bool isTimerPaused; /// <summary> /// タイマー一時停止フラグ の取得および設定 /// </summary> public bool IsTimerPaused { get { return this.isTimerPaused; } set { if (this.SetProperty<bool>(ref this.isTimerPaused, value)) { this.OnIsTimerPausedChanged(); } } } #endregion //IsTimerPaused:タイマー一時停止フラグ プロパティ #region タイマー停止コマンド /// <summary> /// タイマー停止コマンド /// </summary> private ICommand stopCommand; /// <summary> /// タイマー停止コマンド の取得 /// </summary> public ICommand StopCommand { get { return this.stopCommand; } } /// <summary> /// タイマー停止 /// </summary> public void StopTimer() { Monitor.Enter(LockObject); try { this.IsTimerStarted = false; this.TimerValue = this.originValue; this.MaxSeconds = this.originMaxSeconds; } finally { Monitor.Exit(LockObject); } } #endregion //タイマー一時停止コマンド #region IsEnableStop:タイマー停止可能フラグ プロパティ /// <summary> /// タイマー停止可能フラグ /// </summary> private bool isEnableStop; /// <summary> /// タイマー停止可能フラグ の取得および設定 /// </summary> public bool IsEnableStop { get { return this.isEnableStop; } set { this.SetProperty<bool>(ref this.isEnableStop, value); } } #endregion //IsEnableStop:タイマー停止可能フラグ プロパティ
停止の Command のみですが、Command の中に CanStop みたいなコマンド実行可否を返すメソッドを設定せず、IsEnableStop というプロパティで実装しています
Xamarin.Forms でも Command(Action execute, Func
/// <summary> /// Element プロパティ変更イベントハンドラ /// </summary> /// <param name="sender">イベント発行者</param> /// <param name="e">イベント引数</param> protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); switch (e.PropertyName) { case "IsEnableStop": this.stopButton.Enabled = this.Element.IsEnableStop; break; } }
こうしないと OnElementPropertyChanged ViewRenderer に変更を伝搬できないからです;
うーん・・・やっぱり手続きである Command をデータバインドするということ自体に違和感あるし、MVVM ではなくてデータと手続きを分離する MVPVM にしたいところですね