MVVM - powiązania danych WPF

W tym rozdziale dowiemy się, jak powiązanie danych obsługuje wzorzec MVVM. Powiązanie danych jest kluczową funkcją, która odróżnia MVVM od innych wzorców separacji interfejsu użytkownika, takich jak MVC i MVP.

  • W przypadku powiązania danych musisz mieć skonstruowany widok lub zestaw elementów interfejsu użytkownika, a następnie potrzebujesz innego obiektu, na który będą wskazywać powiązania.

  • Elementy interfejsu użytkownika w widoku są powiązane z właściwościami, które są uwidaczniane przez ViewModel.

  • Kolejność, w jakiej są konstruowane View i ViewModel, zależy od sytuacji, ponieważ najpierw omówiliśmy widok.

  • View i ViewModel są konstruowane, a DataContext of the View jest ustawiana na ViewModel.

  • Powiązania mogą być powiązaniami danych OneWay lub TwoWay do przesyłania danych między View i ViewModel.

Przyjrzyjmy się powiązaniom danych w tym samym przykładzie. Poniżej znajduje się kod 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>
  • Jeśli spojrzysz na powyższy kod XAML, zobaczysz, że ItemsControl jest powiązany z kolekcją Students uwidocznioną przez ViewModel.

  • Możesz również zobaczyć, że właściwość modelu ucznia ma również swoje własne indywidualne powiązania, które są powiązane z Textboxami i TextBlock.

  • ItemSource of ItemsControl można powiązać z właściwością Students, ponieważ ogólny DataContext dla widoku jest ustawiony na ViewModel.

  • Poszczególne powiązania właściwości w tym miejscu są również powiązaniami DataContext, ale nie są one powiązane z samym ViewModel ze względu na sposób działania elementu ItemSource.

  • Gdy źródło elementu wiąże się ze swoją kolekcją, renderuje kontener dla każdego elementu podczas renderowania i ustawia DataContext tego kontenera na element. Zatem ogólny DataContext dla każdego pola tekstowego i bloku tekstowego w wierszu będzie stanowić indywidualnego Studenta w kolekcji. Możesz również zobaczyć, że te powiązania dla TextBox to powiązania danych TwoWay, a dla TextBlock jest to powiązanie danych OneWay, ponieważ nie możesz edytować TextBlock.

Po ponownym uruchomieniu tej aplikacji zobaczysz następujące dane wyjściowe.

Zmieńmy teraz tekst w drugim polu tekstowym pierwszego wiersza z Allain na Upston i naciśnij klawisz Tab, aby stracić fokus. Zobaczysz, że tekst TextBlock jest również aktualizowany.

Dzieje się tak, ponieważ powiązania TextBox są ustawione na TwoWay i aktualizuje również Model, a następnie z modelu ponownie aktualizowany jest TextBlock.