Повысить значение PropertyChanged для свойства внутри модели

#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, поэтому я мог бы сделать привязки неправильно, но я был бы признателен, если бы ты уточнил или указал мне на статью, которая могла бы объяснить мне, почему мой способ сделать это неправильно.