Это может быть сложно, и может очень быстро запутаться.
Я бы посоветовал вам придерживаться вашего текущего подхода, предусматривающего использование только одного таймера, который инициализируется в основной модели представления. Затем вам нужно задать себе вопрос - относится ли возраст (TimeSinceStart) виджета к виджету или он предназначен исключительно для демонстрации / в информационных целях? Является ли это основной информацией, которую каждый виджет должен хранить в течение своей жизни?
Мне кажется, это только для демонстрации. Поэтому я предлагаю следующее: как только вы позвоните GetWidgets
, вы можете перечислять каждый виджет и оборачивать его в отдельную тонкую модель представления. Конструктор для этой модели представления принимает два параметра - таймер из основной модели представления и виджет. Затем вы подписываетесь на событие таймера Tick
и после этого уведомляете, что свойство TimeSinceStart
изменилось.
public class WidgetWrapper : INotifyPropertyChanged
{
public WidgetWrapper(DispatcherTimer timer, Widget widget)
{
_widget = widget;
timer.Tick += TimerTick;
}
private void TimerTick(object sender, EventArgs e)
{
OnPropertyChanged("TimeSinceStart");
}
public Widget Widget { get { return _widget; } }
public TimeSpan? TimeSinceStart
{
get { return _widget.Start.HasValue ? DateTime.Now - _widget.Start.Value : default(TimeSpan); }
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
private readonly Widget _widget;
}
public class WidgetDisplayerViewModel : BaseViewModel
{
public WidgetDisplayerViewModel(string selectedCategory) : this()
{
Category = MockDataService.GetCategory(selectedCategory);
var wrappedWidgets = new ObservableCollection<WidgetWrapper>();
MockDataService.GetWidgets(selectedCategory).ForEach(widget => wrappedWidgets.Add(new WidgetWrapper(TimeUpdateTimer, widget)));
Category.Widgets = wrappedWidgets;
}
}
Упаковка DTO (сущности, объекта передачи данных) со своей собственной моделью представления является довольно распространенным подходом при добавлении функциональности к сущности. Если вы используете этот подход, вам придется немного изменить любые привязки пользовательского интерфейса, которые были нацелены на свойства в виджете, поскольку эти элементы пользовательского интерфейса теперь будут иметь дело с WidgetWrapper (или вы можете просто отобразить необходимые свойства в самом WidgetWrapper, а не привязки) надо менять).