MVVM – WPF 資料模板



模板描述了控制元件的整體外觀和視覺效果。每個控制元件都與其關聯了一個預設模板,該模板賦予該控制元件外觀。在 WPF 應用程式中,當您想要自定義控制元件的視覺行為和視覺外觀時,可以輕鬆建立自己的模板。邏輯和模板之間的連線可以透過資料繫結來實現。

在 MVVM 中,還有另一種主要形式,稱為 ViewModel 優先構建。

  • ViewModel 優先構建方法利用了 WPF 中隱式資料模板的功能。

  • 隱式資料模板可以根據使用資料繫結呈現的資料物件型別,自動從當前資源字典中為使用資料繫結的元素選擇合適的模板。首先,您需要有一些繫結到資料物件的元素。

讓我們再次看看我們簡單的示例,您將瞭解如何利用資料模板(特別是隱式資料模板)來實現 ViewModel 優先。以下是我們 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 檔案,刪除現有的實現並在 Resources 部分定義一個數據模板。

<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>

現在新增一個列表框並將該列表框資料繫結到 Students 屬性,如下面的程式碼所示。

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

在 Resource 部分,DataTemplate 的鍵為 studentsTemplate,然後要實際使用該模板,我們需要使用 ListBox 的 ItemTemplate 屬性。因此,現在您可以看到我們指示列表框使用該特定模板來呈現這些 Students。以下是 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 和文字框中。

WPF Data Templates Main Window

要將其設為隱式模板,我們需要從列表框中刪除 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 中的運算子。因此,基本上我們需要指向 MVVMDemo.Model 名稱空間中的 Student 資料型別。以下是更新後的完整 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 自動對映正在呈現的物件的型別。

Data Templates

我們建議您逐步執行上述示例以更好地理解。

廣告

© . All rights reserved.