Учебники

MVVM — шаблоны данных WPF

Шаблон описывает общий вид и внешний вид элемента управления. Для каждого элемента управления есть шаблон по умолчанию, связанный с ним, который создает видимость этого элемента управления. В приложении WPF вы можете легко создавать свои собственные шаблоны, когда вы хотите настроить визуальное поведение и внешний вид элемента управления. Связь между логикой и шаблоном может быть достигнута с помощью привязки данных.

В MVVM есть еще одна первичная форма, известная как первая конструкция ViewModel.

  • Первый метод построения ViewModel использует возможности неявных шаблонов данных в WPF.

  • Неявные шаблоны данных могут автоматически выбирать соответствующий шаблон из текущего словаря ресурсов для элемента, который использует привязку данных. Они делают это в зависимости от типа объекта данных, который отображается связыванием данных. Во-первых, вам нужно иметь некоторый элемент, который привязывается к объекту данных.

Первый метод построения ViewModel использует возможности неявных шаблонов данных в WPF.

Неявные шаблоны данных могут автоматически выбирать соответствующий шаблон из текущего словаря ресурсов для элемента, который использует привязку данных. Они делают это в зависимости от типа объекта данных, который отображается связыванием данных. Во-первых, вам нужно иметь некоторый элемент, который привязывается к объекту данных.

Давайте еще раз посмотрим на наш простой пример, в котором вы поймете, как вы можете сделать модель представления в первую очередь, используя шаблоны данных, особенно неявные шаблоны данных. Вот реализация нашего класса StudentViewModel.

using MVVMDemo.Model; 
using System.Collections.ObjectModel;

namespace MVVMDemo.ViewModel { 

   public class StudentViewModel {
	
      public StudentViewModel() { 
         LoadStudents(); 
      } 
		
      public ObservableCollection<Student> Students { 
         get; 
         set; 
      }
		
      public void LoadStudents() { 
         ObservableCollection<Student> students = new ObservableCollection<Student>();
			
         students.Add(new Student { FirstName = "Mark", LastName = "Allain" }); 
         students.Add(new Student { FirstName = "Allen", LastName = "Brown" }); 
         students.Add(new Student { FirstName = "Linda", LastName = "Hamerski" }); 
			
         Students = students; 
      } 
   } 
}

Вы можете видеть, что вышеупомянутая ViewModel не изменилась. Мы продолжим с тем же примером из предыдущей главы. Этот класс ViewModel просто предоставляет свойство коллекции Students и заполняет его при создании. Давайте перейдем к файлу StudentView.xaml, удалим существующую реализацию и определим шаблон данных в разделе Ресурсы.

<UserControl.Resources> 
   <DataTemplate x:Key = "studentsTemplate">
	
      <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> 
</UserControl.Resources>

Теперь добавьте список и данные, связывающие этот список со свойством «Студенты», как показано в следующем коде.

<ListBox ItemsSource = "{Binding Students}" ItemTemplate = "{StaticResource studentsTemplate}"/>

В разделе «Ресурс» DataTemplate имеет ключ studentTemplate, а затем, чтобы фактически использовать этот шаблон, нам нужно использовать свойство ItemTemplate объекта ListBox. Итак, теперь вы можете видеть, что мы поручаем списку использовать этот конкретный шаблон для рендеринга этих учеников. Ниже приводится полная реализация файла StudentView.xaml.

<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.Resources> 
      <DataTemplate x:Key = "studentsTemplate"> 
		
         <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> 
   </UserControl.Resources>
	
   <Grid> 
      <ListBox 
         ItemsSource = "{Binding Students}" 
         ItemTemplate = "{StaticResource studentsTemplate}"/> 
   </Grid>
	
</UserControl>

Когда приведенный выше код скомпилирован и выполнен, вы увидите следующее окно, которое содержит один ListBox. Каждый ListBoxItem содержит данные объекта класса Student, которые отображаются в полях TextBlock и Text.

Главное окно шаблонов данных WPF

Чтобы сделать этот шаблон неявным, нам нужно удалить свойство ItemTemplate из списка и добавить свойство DataType в определение нашего шаблона, как показано в следующем коде.

<UserControl.Resources> 
   <DataTemplate DataType = "{x:Type data:Student}">
	
      <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> 
</UserControl.Resources>
 
<Grid> 
   <ListBox ItemsSource = "{Binding Students}"/> 
</Grid>

В DataTemplate очень важно расширение разметки x: Type, которое похоже на тип оператора в XAML. Итак, в основном нам нужно указать на тип данных Student, который находится в пространстве имен MVVMDemo.Model. Ниже приведен обновленный полный файл XAML.

<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:data = "clr-namespace:MVVMDemo.Model" 
   xmlns:vml = "clr-namespace:MVVMDemo.VML" 
   vml:ViewModelLocator.AutoHookedUpViewModel = "True" 
   mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "300">
	
   <UserControl.Resources> 
      <DataTemplate DataType = "{x:Type data:Student}"> 
		
         <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> 
   </UserControl.Resources>
	
   <Grid>
      <ListBox ItemsSource = "{Binding Students}"/> 
   </Grid> 
	
</UserControl>

Когда вы снова запустите это приложение, вы все равно получите тот же рендеринг шаблона «Студенты с данными», потому что он автоматически отображает тип визуализируемого объекта, найдя соответствующий DataTemplate.

Шаблоны данных

Мы рекомендуем вам выполнить приведенный выше пример пошаговым методом для лучшего понимания.