かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

MVVMの小さなサンプル サケ弁タイマー2

1つ前のサケ弁タイマーのサンプルですが、Modelに該当する部分をid:anis774さんのコードをマルパクリしていたのをReactive Extensions使うように書き直してみました。

以下からダウンロードできます。

因みにModel部分のコードだけ以下に載せておきます。

namespace YakibenTimer3
{
    using System;
    using System.Linq;
    using Livet;

    public class Model : NotifyObject
    {
        private IDisposable countDown;

        private TimeSpan time;

        private bool isStarted;

        public EventHandler End = delegate { };

        public TimeSpan Time
        {
            get
            {
                return this.time;
            }

            set
            {
                if (this.time == value)
                {
                    return;
                }

                this.time = value;
                if (this.time < TimeSpan.Zero)
                {
                    this.time = TimeSpan.Zero;
                }

                base.RaisePropertyChanged("Time");
            }
        }

        public bool IsStarted
        {
            get
            {
                return this.isStarted;
            }

            set
            {
                if (this.isStarted == value)
                {
                    return;
                }

                this.isStarted = value;
                base.RaisePropertyChanged("IsStarted");
            }
        }

        public void AddTime(TimeSpan timeSpan)
        {
            this.Time += timeSpan;
        }

        public void Start()
        {
            this.countDown = Observable.Timer(TimeSpan.FromMilliseconds(500))
                .Repeat()
                .TimeInterval()
                .Subscribe(time =>
                    {
                        this.Time -= time.Interval;
                        if (this.Time == TimeSpan.Zero)
                        {
                            this.End(this, EventArgs.Empty);
                            this.Reset();
                        }
                    },
                    ex =>
                    {
                        this.Time = TimeSpan.Zero;
                        this.IsStarted = false;
                    },
                    () => { });
        }

        public void Reset()
        {
            this.IsStarted = false;
            this.Time = TimeSpan.Zero;
            if (this.countDown == null)
            {
                return;
            }

            this.countDown.Dispose();
            this.countDown = null;
        }
    }

    /* オリジナル
    using System;

    public class Model : System.ComponentModel.INotifyPropertyChanged
    {
        private System.Threading.Thread thread;

        public TimeSpan Time { get; set; }

        public void AddTime(TimeSpan timeSpan)
        {
            this.Time += timeSpan;
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("Time"));
            }
        }

        public void Start()
        {
            DateTime startTime = DateTime.Now;
            TimeSpan startTimeSpan = TimeSpan.Zero;

            this.thread = new System.Threading.Thread(() =>
            {
                try
                {
                    while (true)
                    {
                        this.Time = startTimeSpan - (DateTime.Now - startTime);
                        if (this.Time <= TimeSpan.Zero)
                        {
                            if (this.End != null)
                            {
                                this.End(this, EventArgs.Empty);
                            }
                            this.Time = TimeSpan.Zero;
                            break;
                        }

                        this.OnPropertyChanged("Time");

                        System.Threading.Thread.Sleep(10);
                    }
                    this.IsStarted = false;
                    this.OnPropertyChanged("IsStarted");
                    this.OnPropertyChanged("Time");
                    System.Threading.Thread.Sleep(10);
                }
                catch (System.Threading.ThreadAbortException)
                {
                    this.Time = TimeSpan.Zero;
                }
            });

            this.thread.IsBackground = true;

            startTime = DateTime.Now;
            startTimeSpan = this.Time;
            this.thread.Start();
            this.IsStarted = true;
            this.OnPropertyChanged("IsStarted");
        }

        public void Reset()
        {
            if (this.thread != null)
            {
                try
                {
                    this.thread.Abort();
                }
                catch { }

                this.thread.Join();
            }

            this.Time = TimeSpan.Zero;
            this.IsStarted = false;

            this.OnPropertyChanged("Time");
            this.OnPropertyChanged("IsStarted");
        }

        public bool IsStarted { get; private set; }

        public event EventHandler End;

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }
    }
     */
}

編集:2011/01/10 17:12 neueccさんの指摘を受けてコードを修正