2014-09-30 2 views
0

У меня есть универсальная/портативная библиотека C# для Windows Phone 8 и Windows 8. На библиотеку будут ссылаться приложения для каждой платформы. В библиотеке есть модель представления, и я пытаюсь поместить таймер в модель представления. Единственным «таймером», доступным в библиотеке для обеих платформ, является System.Threading.Timer (без DispatcherTimer). Однако я не могу обойти проблемы с перекрестными потоками. Есть ли способ сделать это или мне нужно создать таймер в каждом приложении в коде страницы?Таймер в MVVM для Windows Phone 8 и Windows 8


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; } 
} 
+0

В моем представлении базовый класс модели в PCL Я использую метод 'protected abstract void DispatcherInvoke (Action action)', который реализуется производными классами класса модели, ориентированными на платформу. – Clemens

ответ

1

Два возможных решений:

  1. Если вы ориентируетесь Windows 8 и Windows Phone 8,1 (не Phone 8.0 Silverlight), рекомендуется использовать универсальное приложение, содержащее Общий проект вместо портативной библиотеки классов для размещения ваших моделей представлений. Совместные проекты совместимы только с проектами WinRT, но поддерживают полную инфраструктуру WinRT. В этом случае не должно возникнуть проблемы с созданием DispatcherTimer непосредственно в Viewmodel.
  2. В противном случае (в настоящей портативной библиотеке классов) я боюсь, что единственный способ - создать интерфейс в PCL, который обеспечивает наиболее важные функции таймера, и два класса таймера, специфичные для платформы, которые реализуют этот интерфейс. На практике эти две реализации будут идентичны, за исключением операторов using в начале файла, потому что Windows Phone Silverlight DispatcherTimer живет в пространстве имен System.Windows.Threading, а на WinRT он находится по адресу Windows.UI.Xaml, но обе имеют одинаковую функциональность - так что это в основном копия/вставить задание.

    Я реализовал такую ​​разделенную реализацию как часть рамки MVVMbasics, может быть, the sources avaiable at Codeplex - любая помощь!