В этой главе мы рассмотрим различные способы подключения ваших представлений к ViewModel. Во-первых, давайте посмотрим на конструкцию View first, где мы можем объявить ее в XAML. Как мы видели в примере из предыдущей главы, мы подключили вид из главного окна. Теперь мы увидим другие способы подключения просмотров.
Мы будем использовать тот же пример в этой главе. Ниже приведена та же реализация класса Model.
using System.ComponentModel; namespace MVVMDemo.Model { public class StudentModel {} public class Student : INotifyPropertyChanged { private string firstName; private string lastName; public string FirstName { get { return firstName; } set { if (firstName != value) { firstName = value; RaisePropertyChanged("FirstName"); RaisePropertyChanged("FullName"); } } } public string LastName { get { return lastName; } set { if (lastName != value) { lastName = value; RaisePropertyChanged("LastName"); RaisePropertyChanged("FullName"); } } } public string FullName { get { return firstName + " " + lastName; } } public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } } }
Вот реализация класса ViewModel. На этот раз метод LoadStudents вызывается в конструкторе по умолчанию.
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; } } }
Независимо от того, является ли представление окном, пользовательским элементом управления или страницей, парсер обычно работает сверху вниз и слева направо. Он вызывает конструктор по умолчанию для каждого элемента при его обнаружении. Есть два способа построить представление. Вы можете использовать любой на них.
- Посмотреть первую конструкцию в XAML
- Посмотреть первую конструкцию в коде позади
Посмотреть первую конструкцию в XAML
Один из способов — просто добавить вашу ViewModel как вложенный элемент в установщик для свойства DataContext, как показано в следующем коде.
<UserControl.DataContext> <viewModel:StudentViewModel/> </UserControl.DataContext>
Вот полный файл View 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" 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>
Посмотреть первую конструкцию в коде позади
Другой способ заключается в том, что вы можете получить конструкцию View first, просто создав собственную модель представления в коде вашего View, установив там свойство DataContext вместе с экземпляром.
Как правило, свойство DataContext устанавливается в методе конструктора представления, но вы также можете отложить конструкцию, пока не произойдет событие Load представления.
using System.Windows.Controls; namespace MVVMDemo.Views { /// <summary> /// Interaction logic for StudentView.xaml /// </summary> public partial class StudentView : UserControl { public StudentView() { InitializeComponent(); this.DataContext = new MVVMDemo.ViewModel.StudentViewModel(); } } }
Одна из причин создания модели представления в Code-behind вместо XAML заключается в том, что конструктор модели View принимает параметры, но при разборе XAML элементы могут создаваться только в том случае, если они определены в конструкторе по умолчанию.
Теперь в этом случае XAML-файл View будет выглядеть так, как показано в следующем коде.
<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" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "300"> <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>
Вы можете объявить это представление в MainWindow, как показано в файле MainWindow.XAML.
<Window x:Class = "MVVMDemo.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local = "clr-namespace:MVVMDemo" xmlns:views = "clr-namespace:MVVMDemo.Views" mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525"> <Grid> <views:StudentView x:Name = "StudentViewControl"/> </Grid> </Window>
Когда приведенный выше код компилируется и выполняется, вы увидите следующий вывод в главном окне.
Мы рекомендуем выполнить вышеприведенный пример пошагово для лучшего понимания.