かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

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さんの指摘を受けてコードを修正