MVVM - Mẫu dữ liệu WPF
Mẫu mô tả giao diện tổng thể và hình thức trực quan của điều khiển. Đối với mỗi điều khiển, có một mẫu mặc định được liên kết với nó để cung cấp hình thức cho điều khiển đó. Trong ứng dụng WPF, bạn có thể dễ dàng tạo các mẫu của riêng mình khi bạn muốn tùy chỉnh hành vi trực quan và hình thức trực quan của điều khiển. Kết nối giữa logic và mẫu có thể đạt được bằng cách liên kết dữ liệu.
Trong MVVM, có một dạng chính khác được gọi là bản dựng đầu tiên của ViewModel.
Phương pháp tiếp cận xây dựng đầu tiên của ViewModel tận dụng khả năng của các mẫu dữ liệu ngầm trong WPF.
Mẫu dữ liệu ngầm định có thể tự động chọn một mẫu thích hợp từ từ điển tài nguyên hiện tại cho một phần tử sử dụng liên kết dữ liệu. Họ thực hiện điều này dựa trên loại đối tượng dữ liệu được hiển thị bằng liên kết dữ liệu. Đầu tiên, bạn cần có một số phần tử liên kết với một đối tượng dữ liệu.
Hãy xem lại ví dụ đơn giản của chúng tôi, trong đó bạn sẽ hiểu cách bạn có thể thực hiện chế độ xem mô hình trước tiên tận dụng các mẫu dữ liệu, cụ thể là các mẫu dữ liệu ngầm định. Đây là việc triển khai lớp StudentViewModel của chúng tôi.
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;
}
}
}
Bạn có thể thấy rằng ViewModel ở trên là không thay đổi. Chúng ta sẽ tiếp tục với ví dụ tương tự từ chương trước. Lớp ViewModel này chỉ hiển thị thuộc tính bộ sưu tập Sinh viên và đưa nó vào quá trình xây dựng. Hãy chuyển đến tệp StudentView.xaml, loại bỏ triển khai hiện có và xác định mẫu dữ liệu trong phần Tài nguyên.
<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>
Bây giờ, thêm một hộp danh sách và dữ liệu liên kết hộp danh sách đó với thuộc tính Sinh viên như được hiển thị trong đoạn mã sau.
<ListBox ItemsSource = "{Binding Students}" ItemTemplate = "{StaticResource studentsTemplate}"/>
Trong phần Resource, DataTemplate có một khóa là studentTemplate và để thực sự sử dụng mẫu đó, chúng ta cần sử dụng thuộc tính ItemTemplate của một ListBox. Vì vậy, bây giờ bạn có thể thấy rằng chúng tôi hướng dẫn hộp danh sách sử dụng mẫu cụ thể đó để hiển thị các Học sinh đó. Sau đây là quá trình triển khai hoàn chỉnh tệp 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>
Khi đoạn mã trên được biên dịch và thực thi, bạn sẽ thấy cửa sổ sau chứa một ListBox. Mỗi ListBoxItem chứa dữ liệu đối tượng lớp Sinh viên được hiển thị trên TextBlock và hộp Văn bản.
Để làm cho đây là một mẫu ngầm định, chúng ta cần xóa thuộc tính ItemTemplate khỏi hộp danh sách và thêm thuộc tính DataType vào định nghĩa mẫu của chúng tôi như được hiển thị trong đoạn mã sau.
<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>
Trong DataTemplate, phần mở rộng đánh dấu x: Type rất quan trọng, nó giống như một loại toán tử trong XAML. Vì vậy, về cơ bản chúng ta cần trỏ đến kiểu dữ liệu Sinh viên trong không gian tên MVVMDemo.Model. Sau đây là tệp XAML hoàn chỉnh được cập nhật.
<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>
Khi bạn chạy lại ứng dụng này, bạn sẽ vẫn nhận được kết xuất tương tự của Mẫu dữ liệu sinh viên vì nó tự động ánh xạ loại đối tượng đang được hiển thị bằng cách định vị DataTemplate thích hợp.
Chúng tôi khuyên bạn nên thực hiện ví dụ trên theo phương pháp từng bước để hiểu rõ hơn.