Учебники

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

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

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

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

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

  • View и ViewModel создаются, а DataContext для View устанавливается в ViewModel.

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

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

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

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

View и ViewModel создаются, а DataContext для View устанавливается в 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 of ItemsControl может связываться со свойством Students, поскольку общий DataContext для View установлен на ViewModel.

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

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

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

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

ItemSource of ItemsControl может связываться со свойством Students, поскольку общий DataContext для View установлен на ViewModel.

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

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

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

Главное окно привязок данных WPF

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

Обновленный текстовый блок

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