适用于Windows Phone 8和Windows 8的MVVM中的计时器



我有一个适用于Windows Phone 8和Windows 8的通用/可移植C#库。每个平台的应用程序都会引用该库。库中有一个视图模型,我正试图在视图模型中放置一个计时器。两个平台的库中唯一可用的"Timer"是System.Threading.Timer(没有DispatcherTimer)。但是,我无法解决跨线程问题。有没有办法做到这一点,或者我必须在页面代码后面的每个应用程序中创建一个计时器?


public class DefaultViewModel : INotifyPropertyChanged
{
    System.Threading.Timer _Timer;
    public DefaultViewModel()
    {
        this.ToggleStartStopCommand = new Command(ToggleStartStop, true);
    }
    private TimeSpan _Duration;
    public TimeSpan Duration
    {
        get { return this._Duration; }
        set
        {
            if (value != this._Duration)
            {
                this._Duration = value;
                this.RaisePropertyChanged("Duration"); // Error occurs here
            }
        }
    }
    private bool _IsRunning;
    public bool IsRunning
    {
        get { return this._IsRunning; }
        set
        {
            if (value != this._IsRunning)
            {
                this._IsRunning = value;
                this.RaisePropertyChanged("IsRunning");
            }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    public virtual void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if (null != propertyChanged)
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    public void Start()
    {
        this.IsRunning = true;
        this._Timer = new Timer(TimerTick, this, 0, 1000);
    }
    private DateTime _StartTime;
    public DateTime StartTime
    {
        get { return this._StartTime; }
        set
        {
            if (value != this._StartTime)
            {
                this._StartTime = value;
                this.RaisePropertyChanged("StartTime");
            }
        }
    }
    public void Stop()
    {
        this._Timer.Dispose();
        this.IsRunning = false;
    }
    private void TimerTick(object o)
    {
        var defaultViewModel = (DefaultViewModel)o;
        defaultViewModel.Duration = DateTime.Now - defaultViewModel.StartTime;
    }
    public void ToggleStartStop()
    {
        if (this.IsRunning)
            this.Stop();
        else
            this.Start();
    }
    public Command ToggleStartStopCommand { get; private set; }
}

两种潜在的解决方案:

  1. 如果您的目标是Windows 8和Windows Phone 8.1(而不是Phone 8.0 Silverlight),请考虑使用包含共享项目的通用应用程序而不是可移植类库来托管Viewmodel。共享项目仅与WinRT项目兼容,但支持完整的WinRT框架。在这种情况下,直接在Viewmodel中实例化DispatcherTimer应该不会有问题。

  2. 否则(在一个真正的可移植类库中),恐怕唯一的方法就是在PCL中创建一个接口,提供最重要的定时器功能,以及实现该接口的两个特定于平台的定时器类。在实践中,除了文件开头的using语句外,这两个实现将是相同的,因为Windows Phone Silverlight的DispatcherTimer位于System.Windows.Threading命名空间中,而在WinRT上,它位于Windows.UI.Xaml,但两者具有相同的功能,因此它基本上是一个复制/粘贴作业。

    作为MVVMbasics框架的一部分,我已经实现了这样一个分离的实现,也许Codeplex上可用的源代码有任何帮助!

最新更新