MVVM - шаблоны данных WPF
Шаблон описывает общий вид и внешний вид элемента управления. Для каждого элемента управления есть связанный с ним шаблон по умолчанию, который придает внешний вид этому элементу управления. В приложении WPF вы можете легко создавать свои собственные шаблоны, если хотите настроить визуальное поведение и внешний вид элемента управления. Связь между логикой и шаблоном может быть достигнута путем привязки данных.
В MVVM есть еще одна основная форма, известная как первая конструкция ViewModel.
Первый подход к построению 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 просто предоставляет свойство коллекции Student и заполняет его при создании. Перейдем к файлу 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, которые отображаются в текстовых блоках и текстовых полях.
Чтобы сделать этот шаблон неявным, нам нужно удалить свойство 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.
Мы рекомендуем вам выполнить приведенный выше пример пошаговым методом для лучшего понимания.