淺談WPF之各種Template

来源:https://www.cnblogs.com/hsiang/archive/2023/11/22/17845333.html
-Advertisement-
Play Games

前幾天寫了一篇文章【淺談WPF之控制項模板和數據模板】,有粉絲反饋說這兩種模板容易弄混,不知道什麼時候該用控制項模塊,什麼時候該用數據模板,以及template和itemtemplate之間的關係等,今天專門寫一篇文章,簡述WPF中各種模板及其相互關係。僅供學習分享使用,如有不足之處,還請指正。 ...


前幾天寫了一篇文章【淺談WPF之控制項模板和數據模板】,有粉絲反饋說這兩種模板容易弄混,不知道什麼時候該用控制項模塊,什麼時候該用數據模板,以及template和itemtemplate之間的關係等,今天專門寫一篇文章,簡述WPF中各種模板及其相互關係。僅供學習分享使用,如有不足之處,還請指正。

 

概述

在WPF中,一共有三種模板,分別如下:

  • 控制項模板ControlTemplate,用來指定控制項的呈現樣式。
  • 數據模板DataTemplate,用來指定子項數據的呈現樣式。
  • 子控制項模板ItemPanelTemplate,用來指定子項控制項的佈局樣式。

 

模板與控制項之間的關係

 

關於各個模板與控制項之間的關係,如下圖所示:

通過上圖可以看出:

  1. Control擁有Template屬性,是ControlTemplate類型,所有Control派生的子控制項,都具有Template屬性,都可以通過控制項模板設置控制項的樣式。
  2. ContentControl擁有ContentTemplate屬性,是DataTemplate類型,所有ContentControl派生的控制項,都具有ContentTemplate屬性,如Button,ListBoxItem,DataGridCell等。
  3. ItemsControl擁有ItemsTemplate屬性,是DataTemplate類型,所有ItemsControl派生的控制項,都具有ItemsTemplate屬性,如ListBox,ComboBox,DataGrid,ListView等。
  4. ItemsControl擁有ItemsPanel屬性,是ItemsPanelTemplate類型,所有ItemsControl派生的控制項,都具有ItemsPanel屬性,如ListBox,ComboBox,DataGrid,ListView等。
  5. Template,ContentTemplate,ItemsTemplate,ItemsPanel只是屬性名稱,而DataTemlate,ControlTemplate,ItemsPanelTemplate才是模板類型。

 

ControlTemplate控制項模板詳解

 

利用ControlTemplate可以徹底的顛覆控制項的預設外觀。<ControlTemplate>裡面的內容就是視覺樹VisualTree。
兩個重要屬性:

a)ContentPresenter

重定義控制項模板,預設模板將會被覆蓋,此時需要利用ContentPresenter,把原有模板的屬性原封不動的投放到自定義模板中。

b)Triggers

觸發器列表,裡面包含一些觸發器Trigger,我們可以定製這個觸發器列表來使控制項對外界的刺激發生反應,比如滑鼠經過時文本變成粗體等。

控制項模板示例

<Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:sys="clr-namespace:System;assembly=mscorlib"
         Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ControlTemplate x:Key="rect" TargetType="{x:Type CheckBox}">
            <ControlTemplate.Resources>
                <SolidColorBrush x:Key="redBrush" Color="Red"/>
            </ControlTemplate.Resources>
            <StackPanel>
                <Rectangle Name="breakRectangle" Stroke="Red" StrokeThickness="2" Width="20" Height="20">
                    <Rectangle.Fill>
                        <SolidColorBrush Color="White"/>
                    </Rectangle.Fill>
                </Rectangle>
                <ContentPresenter/>
            </StackPanel>
            <ControlTemplate.Triggers>
                <Trigger Property="IsChecked" Value="True">
                    <Setter TargetName="breakRectangle" Property="Fill" Value="{StaticResource ResourceKey=redBrush}">
                    </Setter>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Window.Resources>
    <Canvas>
        <CheckBox Template="{StaticResource ResourceKey=rect}"  Content="我是CheckBox"/>
    </Canvas>
</Window>

註意:<ContentPresenter Margin="{TemplateBinding Padding}" /> 實現了將模板中的Margin綁定到原控制項中的Padding上去。

將控制項模板寫到樣式裡面,如下所示:

<Style x:Key="cbx" TargetType="{x:Type CheckBox}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">
                <ControlTemplate.Resources>
                    <SolidColorBrush x:Key="redBrush" Color="Red"/>
                </ControlTemplate.Resources>
                <StackPanel>
                    <Rectangle Name="breakRectangle" Stroke="Red" StrokeThickness="2" Width="20" Height="20">
                        <Rectangle.Fill>
                            <SolidColorBrush Color="White"/>
                        </Rectangle.Fill>
                    </Rectangle>
                    <ContentPresenter/>
                </StackPanel>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter TargetName="breakRectangle" Property="Fill" Value="{StaticResource ResourceKey=redBrush}">
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

通過綁定樣式資源,如下所示:

<CheckBox Style="{StaticResource ResourceKey=cbx}" Content="我是CheckBox"/>

 

c)ItemsPresenter

 

繼承自ItemsControl的控制項,有一個ItemsPanel屬性作為集合元素承載容器。子元素ItemsPresenter負責呈現控制項的任務。

只要把ItemsPresenter放在內部模板中,那麼ItemsPresenter則會去檢測父元素是否為集合控制項,然後將ItemsPanel添加到其內部視覺樹當中。

<Style x:Key="{x:Type ItemsControl}" TargetType="{x:Type ItemsControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ItemsControl}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Padding="{TemplateBinding Padding}"
                        SnapsToDevicePixels="true">
                    <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

比較常見的繼承自ItemsControl的控制項,比如ComboBox,ContextMenu,ListBox,DataGrid,ListView等。

 

DataTemplate數據模板詳解

 

數據模板定義了數據的顯示方式,也就是數據對象的可視結構。主要是可以自定義控制項的同時進行數據綁定。

<Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:src="clr-namespace:WpfApplication1"
         Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ObjectDataProvider x:Key="personList" ObjectType="{x:Type src:PersonList}"/>
        <DataTemplate x:Key="rect">
            <Border Name="border" BorderBrush="Aqua" BorderThickness="1" Padding="5" Margin="5">
                <StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
                        <TextBlock Text="{Binding Age}" Margin="5,0,0,0"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Address}" Margin="5,0,0,0"/>
                    </StackPanel>
                </StackPanel>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding Source={StaticResource ResourceKey=personList}}"
                  ItemTemplate="{StaticResource ResourceKey=rect}"></ListBox>
    </Grid>
</Window>

註意這裡在調用時應該綁定的是 ItemTemplate 屬性。 

 

ItemPanelTemplate詳解

 

首先我們要知道常見的條目控制項有:ListBox,Menu,StatusBar等。

比如拿ListBox來說,ItemBox的ItemPanel其實是一個VisualizingStackPanel,就是說ListBox的每一項的排列方式是遵循StackPanel的

原則,也就是從上到下的排列方式。如果要實現從左到右排列:

<Window x:Class="WpfApplication1.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:src="clr-namespace:WpfApplication1"
         Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ObjectDataProvider x:Key="personList" ObjectType="{x:Type src:PersonList}"/>
        <DataTemplate x:Key="rect">
            <Border Name="border" BorderBrush="Aqua" BorderThickness="1" Padding="5" Margin="5">
                <StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
                        <TextBlock Text="{Binding Age}" Margin="5,0,0,0"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Address}" Margin="5,0,0,0"/>
                    </StackPanel>
                </StackPanel>
            </Border>
        </DataTemplate>
        <ItemsPanelTemplate x:Key="items">
            <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        </ItemsPanelTemplate>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding Source={StaticResource ResourceKey=personList}}"
                  ItemTemplate="{StaticResource ResourceKey=rect}" ItemsPanel="{StaticResource ResourceKey=items}"></ListBox>
    </Grid>
</Window>

也就是說,ItemsPanelTemplate可以用來定義集合控制項的容器外觀。

 

總結

 

1、Template


控制項模板,是指整個控制項的展示和佈局。
如ComboBox,可分為文本區域,下拉按鈕區域,Items的Popup區域。
Template就是管理這些位置的佈局。

2、ItemsPresenter


可以簡單理解為占位符,在樣式中使用,標記著這個區域用來展示該控制項的Items。
如:ComboBox的下拉列表的可選項。
但是,只負責顯示,而不能管理如何顯示,如果我們要內容橫向排列,就要用到ItemsPanel。

3、ItemsPanel


管理Items的排列方式,如,ComboBox預設是豎直排列的,我們要橫著排列,只需要定義ItemsPanel為WrapPanel,就可以了。
這時候Items的排列方式已經完成,如果還要讓ComboBox的每個項都重寫,比如,背景、圖標等,就要用到ItemContainerStyle。

4、ItemContainerStyle


就是每個項的樣式,自己重寫,就可以定製出每個項的樣式了。

以上就是淺談WPF之各種模板的全部內容。


作者:小六公子
出處:http://www.cnblogs.com/hsiang/
本文版權歸作者和博客園共有,寫文不易,支持原創,歡迎轉載【點贊】,轉載請保留此段聲明,且在文章頁面明顯位置給出原文連接,謝謝。
關註個人公眾號,定時同步更新技術及職場文章


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • filter, reduce, 和 map 是Python中用於對集合數據進行處理和轉換的內置函數。它們分別用於篩選、歸約和映射集合中的元素。 filter 函數: filter(function, iterable) 用於篩選集合中的元素。它接受一個函數 function 和一個可迭代的對象 it ...
  • 在數據科學計算、機器學習、以及深度學習領域,Python 是最受歡迎的語言。Python 在數據科學領域,有非常豐富的包可以選擇,numpy、scipy、pandas、scikit-learn、matplotlib。 但這些庫都僅僅受限於單機運算,當數據量很大時,比如50GB甚至500GB的數據集, ...
  • 創建資料庫 (xxl-job) 導入相關表 Sql SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- -- Table structure for xxl_job_group -- DROP TABLE IF EXISTS `xxl_job_grou ...
  • 原文鏈接:https://openaigptguide.com/grok-ai/ Grok AI是由馬斯克推出的一款高級別的人工智慧大語言模型,旨在幫助軟體開發者以不同的口頭語言交流和表達。它是基於多種深度學習大規模固定模型架構,如ELMo、BERT和GPT,以及更多新的模式,使軟體開發者能夠快速設 ...
  • 公眾號「架構成長指南」,專註於生產實踐、雲原生、分散式系統、大數據技術分享。 在本教程中,您將通過大量示例來學習 Java 8 Stream API。 Java 在 Java 8 中提供了一個新的附加包,稱為 java.util.stream。該包由類、介面和枚舉組成,允許對元素進行函數式操作。 您 ...
  • 主要介紹了Java的Spring框架中的註解編程。第一章首先介紹了註解編程的概念,即在類或方法上添加特定的註解來完成特定功能的開發。然後解釋了為什麼要學習註解編程,主要原因是註解開發方便且與Spring框架的發展潮流相符合。接著介紹了註解的作用,包括替換XML配置和替換介面實現調用雙方的契約性。第四... ...
  • 一個提供互動式的Web UI用於生成相容MyBatisPlus框架的相關功能代碼的工具,代碼生成包括Entity、Mapper、Mapper.xml、Service、Controller等。 ...
  • 註:之前搭建的windows失敗,因為最終發現openface開源代碼中的torch_neural_net.py的某一路徑並不是windows的文件路徑,所以直接改用最簡便的docker使用。 實現需求目標: 實現兩張照片對人臉進行比對判斷是否為同一個人 openface環境搭建步驟 安裝docke ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...