WPF(MVVM) почему люди которые создают Controll, делают событие не для паттерна MVVM dependency property?

Допустим есть у меня контрол
paz:ZoomBorder

И у него есть событие ZoomChanged="" и это событие не dependency property

введите сюда описание изображения

И теперь вопрос почему все делают такие контроллы?
И если я хочу при вызове события ZoomChanged обрабатывать его в ViewModel, как мне это сделать?
И еще один вопрос. Также есть допустим TextBox и у него есть разные событие такие как: Tapped, DoubleTapped, PointerEnter ....

введите сюда описание изображения

введите сюда описание изображения

И как же мне их обрабатывать в ViewModel когда они вызываются?


Ответы (1 шт):

Автор решения: Kalmankantaja

И если я хочу при вызове события ZoomChanged обрабатывать его в ViewModel , как мне это сделать?

И еще один вопрос. Также есть допустим TextBox и у него есть разные событие такие как: Tapped, DoubleTapped, PointerEnter, как же мне их обрабатывать в ViewModel когда они вызываются?

Не нужно так делать. События View должны обрабатываться внутри View (например - триггеры в xaml или же подписка на события контрола внутри окна), а не внутри ViewModel. Хоть и ViewModel является связующим звеном между доменной логикой и представлением, но оно ничего не должно знать об окне где его используют. Все, что находится в окне - делается внутри окна и нигде больше. События, цвета, шрифты и то что вы видите человеческим глазом - всё это часть представления которое меняется по щелчку пальцев и будет изменяться по ходу приложения еще 100500 раз. Чтобы избежать сильной связанности между представлением и логикой разделяют ответственности и в итоге окно отвечает само за себя.

Как же правильно? Да очень просто:

Сделаем обработчик события (его можно задать как в xaml так и внутри конструктора например, просто обратиться к событию myTextbox.DoubleTapped += OnDoubleTapped, и тогда не нужно будет привязывать через xaml, тут как удобно)

public class MyMainWindow : Window
{
   private void OnDoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
   {
      (sender as TextBox).Text = Guid.NewGuid().ToString();
   }
}

Теперь можно сделать ViewModel. Для начала реализует INPC и сделаем метод SetProperty чтобы было легче писать код и вызывать событие. Так же добавлю свойство VMText которое привяжем в xaml (назвал так для отличия свойства контрола и свойства вьюмодели)

public class MyMainViewModel : INotifyPropertyChanged
{

   private string _text;
   public string VMText { get => _text; set => SetProperty(ref _text, value); }
     
   public event PropertyChangedEventHandler? PropertyChanged;
   protected void OnPropertyChanged([CallerMemberName] string prop = "")
   {
     PropertyChanged?.Invoke(this. new(prop));
   }
   protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string prop = "")
   {
      if(field == value)
         return false;
      
      field = value;
      OnPropertyChanged(prop);
      return true;
   }
}

Можно перейти к xaml окна:

<TextBox Text={Binding VMText} DoubleTapped="OnDoubleTapped"/>

Теперь при вызове события DoubleTapped будет задаваться новый Guid и так же обновляться свойство во ViewModel которым вы можете пользоваться.


Сегодня Вы делаете проект на WPF, а завтра злой директор сказал: надо на ASP.NET Core да еще и чтоб слайдер картинок был, а у вас вся ViewModel захардкожена под WPF и слайдер реализован не внутри окна, а внутри ViewModel. Представляете сколько вы потратите времени просто на то чтобы переписать и захардкодить свою ViewModel под другой тип проекта снова? Вот и я не представляю. Думайте о масштабировании

→ Ссылка