#c# #wpf #binding #mvvm
#c# #wpf #привязка #mvvm
Вопрос:
Итак, у меня есть TimerModel, которая содержит данные для объекта, и TimerViewModel, которая обрабатывает такты таймера от каждого из таймеров. Это просто уменьшает интервал времени, установленный в качестве интервала для таймера — я делаю это исключительно потому, что мне нужно обновить представление за оставшееся время.
public class TimerModel
{
public TimerModel(TimeSpan Interval, TimerViewModel Parent)
{
Timer = new DispatcherTimer();
Timer.Interval = TimeSpan.FromSeconds(1);
parent = Parent;
this.Interval = Interval;
Timer.Tick = (sender, args) => parent._timer_Tick(this, args);
Timer.Start();
}
private TimerViewModel parent;
public DispatcherTimer Timer
{
get;
private set;
}
public TimeSpan Interval
{
get;
set;
}
}
И TimerViewModel будет:
public class TimerViewModel : ViewModelBase
{
public TimerViewModel()
{
Timers = new ObservableCollection<TimerModel>();
AddTimerCommand = new RelayCommand((object x) => { AddTimer(x); });
}
public ObservableCollection<TimerModel> Timers
{
get;
private set;
}
public ICommand AddTimerCommand
{
get;
private set;
}
private void AddTimer(object s)
{
Timers.Add(new TimerModel(TimeSpan.FromSeconds(250), this));
}
internal void _timer_Tick(object sender, EventArgs e)
{
TimerModel timer = sender as TimerModel;
timer.Interval = timer.Interval.Subtract(TimeSpan.FromSeconds(1));
RaisePropertyChanged("Timers");
}
}
Которое привязано к listbox:
<ListBox x:Name="lst_timers" Height="300" Width="150" HorizontalAlignment="Left"
DataContext="{Binding local:TimerViewModel}" ItemsSource="{Binding Timers}"
DisplayMemberPath="Interval" />
_timer_Tick должно повышать измененное свойство для всего списка, но, по-видимому, элементы listbox остаются неизменными.
Кто-нибудь может дать мне подсказку, чего мне здесь не хватает?
Комментарии:
1. Вы вызываете событие в событии _timer_tick, но я не вижу, чтобы вы меняли таймеры. откуда вы вызываете AddTime?,
2. Я вызываю AddTimer из команды, привязанной к элементу управления button, который не имеет отношения к текущей проблеме, учитывая, что он успешно добавляет таймер, но позже он не обновляется.
Ответ №1:
Timers
Список не меняется, изменяется Interval
свойство Timer
объекта.
Я бы предложил ViewModel для всего вашего представления (заданный как DataContext для вашего окна / элемента управления …, а не для ListBox внутри этого родительского окна / элемента управления), содержащий свойство Timers
типа ObervableCollection<TimerViewModel>
. Это TimerViewModel
представляет один единственный таймер и должно вызвать PropertyChanged
-событие для "Interval"
в установщике свойства.
(Дополнительную информацию смотрите в комментариях)
Комментарии:
1. Точно, но я понятия не имею, как этого добиться, не могли бы вы поделиться примером? РЕДАКТИРОВАТЬ: насколько я вас понимаю, я должен внедрять INotifyPropertyChanged в модель? Разве это не противоречило бы рекомендациям MVVM?
2. Вы привязываете модель к представлению (ItemsSoure= Таймеры). На мой взгляд, это уже противоречит рекомендациям MVVM 😉 Я думаю, вам нужна ViewModel, представляющая один таймер со свойствами, необходимыми для вашего просмотра (интервал …). Эта ViewModel привязана к представлению и вызывает необходимое событие. PS: Я могу добавить пример позже, если он вам понадобится…
3. Имеет смысл, но как бы я привязал иначе? Я все еще пытаюсь правильно разобраться в MVVM, поэтому приветствуется любой совет! Должен ли я создать viewmodel, который содержит наблюдаемую коллекцию viewmodels?
4. Да, я бы предложил ViewModel для всего вашего представления (заданный как
DataContext
для вашего окна / элемента управления …, а не для ListBox внутри этого родительского окна / элемента управления), содержащий свойствоTimers
типаObervableCollection<TimerViewModel>
. Этот TimerViewModel представляет один единственный таймер.5. Имеет смысл и открывает целую кучу новых возможностей! Я думал, что не должен был этого делать. Собираюсь проверить это через некоторое время, когда я перепишу это и пометлю это как ответ — также вы можете отредактировать это и указать, что ваш ответ находится в комментариях.
Ответ №2:
<ListBox x:Name="lst_timers" ...>
<ListBox.DataContext>
<local:TimerViewModel/>
</ListBox.DataContext>
</ListBox>
Комментарии:
1. Это уже было сделано…
DataContext="{Binding local:TimerViewModel}
2. Эта часть работала совершенно правильно, обратитесь к ответу Стефана, чтобы узнать, какие проблемы у меня возникли.
3. Энди, я должен извиниться перед тобой, я только что пришел к выводу, что я сделал привязки в коде, лежащем в основе file, поэтому я мог бы сделать привязки неправильно, но я был бы признателен, если бы ты уточнил или указал мне на статью, которая могла бы объяснить мне, почему мой способ сделать это неправильно.