MVVM - привязки данных WPF

В этой главе мы узнаем, как привязка данных поддерживает шаблон MVVM. Привязка данных - это ключевая функция, которая отличает MVVM от других шаблонов разделения пользовательского интерфейса, таких как MVC и MVP.

  • Для привязки данных вам необходимо создать представление или набор элементов пользовательского интерфейса, а затем вам понадобится какой-то другой объект, на который будут указывать привязки.

  • Элементы пользовательского интерфейса в представлении привязаны к свойствам, которые предоставляет ViewModel.

  • Порядок построения View и ViewModel зависит от ситуации, так как мы сначала рассмотрели View.

  • Создается представление и ViewModel, и DataContext представления устанавливается в ViewModel.

  • Привязки могут быть привязками данных OneWay или TwoWay для обмена данными между View и ViewModel.

Давайте посмотрим на привязки данных в том же примере. Ниже представлен код XAML для StudentView.

<UserControl x:Class = "MVVMDemo.Views.StudentView" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:local = "clr-namespace:MVVMDemo.Views" 
   xmlns:viewModel = "clr-namespace:MVVMDemo.ViewModel" 
   xmlns:vml = "clr-namespace:MVVMDemo.VML" 
   vml:ViewModelLocator.AutoHookedUpViewModel = "True" 
   mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "300">

   <!--<UserControl.DataContext> 
      <viewModel:StudentViewModel/> 
   </UserControl.DataContext>--> 

   <Grid> 
      <StackPanel HorizontalAlignment = "Left"> 
         <ItemsControl ItemsSource = "{Binding Path = Students}"> 
            <ItemsControl.ItemTemplate>
               <DataTemplate> 
					
                  <StackPanel Orientation = "Horizontal"> 
                     <TextBox Text = "{Binding Path = FirstName, Mode = TwoWay}" 
                        Width = "100" Margin = "3 5 3 5"/>
								
                     <TextBox Text = "{Binding Path = LastName, Mode = TwoWay}" 
                        Width = "100" Margin = "0 5 3 5"/> 
								
                     <TextBlock Text = "{Binding Path = FullName, Mode = OneWay}" 
                        Margin = "0 5 3 5"/> 
								
                  </StackPanel> 
						
               </DataTemplate> 
            </ItemsControl.ItemTemplate> 
         </ItemsControl> 
      </StackPanel> 
   </Grid> 

</UserControl>
  • Если вы посмотрите на приведенный выше код XAML, вы увидите, что ItemsControl привязан к коллекции студентов, предоставляемой ViewModel.

  • Вы также можете видеть, что свойство модели Student также имеет свои собственные индивидуальные привязки, и они привязаны к Textboxes и TextBlock.

  • ItemSource элемента ItemsControl может быть привязан к свойству Student, поскольку для общего контекста данных для представления установлено значение ViewModel.

  • Отдельные привязки свойств здесь также являются привязками DataContext, но они не привязаны к самой ViewModel из-за того, как работает ItemSource.

  • Когда источник элемента связывается со своей коллекцией, он визуализирует контейнер для каждого элемента при визуализации и устанавливает DataContext этого контейнера для элемента. Таким образом, общий DataContext для каждого текстового поля и текстового блока в строке будет отдельным Student в коллекции. И вы также можете видеть, что эти привязки для TextBoxes являются привязкой данных TwoWay, а для TextBlock - привязкой данных OneWay, поскольку вы не можете редактировать TextBlock.

Когда вы снова запустите это приложение, вы увидите следующий результат.

Давайте теперь изменим текст во втором текстовом поле первой строки с Allain на Upston и нажмем вкладку, чтобы потерять фокус. Вы увидите, что текст TextBlock также обновлен.

Это связано с тем, что привязки TextBoxes установлены на TwoWay, и он также обновляет модель, а из модели снова обновляется TextBlock.