背水一戰 Windows 10 (79) - 自定義控制項: Layout 系統, 控制項模板, 事件處理

来源:http://www.cnblogs.com/webabcd/archive/2017/12/18/8056042.html
-Advertisement-
Play Games

背水一戰 Windows 10 之 控制項(自定義控制項): 自定義控制項的 Layout 系統, 自定義控制項的控制項模板和事件處理的相關知識點 ...


[源碼下載]


背水一戰 Windows 10 (79) - 自定義控制項: Layout 系統, 控制項模板, 事件處理



作者:webabcd


介紹
背水一戰 Windows 10 之 控制項(自定義控制項)

  • 自定義控制項的 Layout 系統
  • 自定義控制項的控制項模板和事件處理的相關知識點



示例
1、演示自定義控制項的 Layout 系統
/MyControls/MyControl2.cs

/*
 * 本例通過一個自定義控制項來演示 uwp 中可視元素的 Layout 系統
 * 
 * uwp 的 layout 是一個遞歸系統,本 demo 就遞歸的一個過程做說明(步驟順序參見代碼註釋中的序號)
 * 
 * 
 * Measure() 的作用是測量尺寸
 * Arrange() 的作用是排列元素
 */

using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml;
using Windows.Foundation;
using System;
using System.Linq;
using System.Diagnostics;
using System.Collections.Generic;

namespace MyControls
{
    /// <summary>
    /// 一個每行都會自動縮進的 Panel
    /// </summary>
    public sealed class MyControl2 : Panel
    {
        // 相對上一行的縮進值
        const double INDENT = 20;

        public MyControl2()
        {

        }

        // 1、首先爸爸知道自己能夠提供的尺寸 availableSize,然後告訴兒子們
        protected override Size MeasureOverride(Size availableSize) // 測量出期待的尺寸並返回
        {
            // 2、兒子們收到 availableSize 後,又結合了自身的實際情況,然後告訴爸爸兒子們所期望的尺寸 desiredSize
            List<double> widthList = new List<double>();
            Size desiredSize = new Size(0, 0);
            foreach (UIElement child in this.Children)
            {
                // 如果 child 是 FrameworkElement 的話,則當調用其 Measure() 方法時會自動調用其 MeasureOverride() 方法
                child.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
                widthList.Add(child.DesiredSize.Width);
                desiredSize.Height += child.DesiredSize.Height;
            }

            if (this.Children.Count > 0)
            {
                desiredSize.Width = widthList.Max();
                desiredSize.Width += INDENT * (this.Children.Count - 1);
            }

            Debug.WriteLine("availableSize: " + availableSize.ToString());
            Debug.WriteLine("desiredSize: " + desiredSize.ToString());

            return desiredSize;
        }

        // 3、爸爸收到兒子們的反饋後,告訴兒子們自己最終提供的尺寸 finalSize
        protected override Size ArrangeOverride(Size finalSize) // 排列元素,並返回呈現尺寸
        {
            // 4、兒子們根據 finalSize 安排各自的位置,然後爸爸的呈現尺寸也就確定了 renderSize
            Point childPosition = new Point(0, 0);
            foreach (UIElement child in this.Children)
            {
                // 如果 child 是 FrameworkElement 的話,則當調用其 Arrange() 方法時會自動調用其 ArrangeOverride() 方法
                child.Arrange(new Rect(childPosition, new Size(child.DesiredSize.Width, child.DesiredSize.Height)));
                childPosition.X += INDENT;
                childPosition.Y += child.DesiredSize.Height;
            }

            Size renderSize = new Size(0, 0);
            renderSize.Width = finalSize.Width;
            renderSize.Height = childPosition.Y;

            Debug.WriteLine("finalSize: " + finalSize.ToString());
            Debug.WriteLine("renderSize: " + renderSize.ToString());

            return finalSize;
        }
    }
}


/*
 * 輸出結果如下(運行 /Controls/CustomControl/Demo2.xaml 示例)
 * availableSize: 800,Double.PositiveInfinity
 * desiredSize: 141,120
 * finalSize: 800,120
 * renderSize: 800,120
*/


/*
 * 註:
 * UIElement
 *     調用 Measure() 方法後會更新 DesiredSize 屬性
 *     調用 Arrange() 方法後會更新 RenderSize 屬性
 *     UpdateLayout() - 強制 layout 遞歸更新
 * 
 * FrameworkElement - 繼承自 UIElement
 *     MeasureOverride() - 在 Measure() 中自動調用
 *     ArrangeOverride() - 在 Arrange() 中自動調用
 *     ActualWidth 和 ActualHeight 來自 RenderSize,每次 UpdateLayout() 後都會被更新
 */


/*
* 註:
* 1、uwp 的 layout 是一個遞歸系統
* 2、UIElement 的 InvalidateMeasure() 就是遞歸調用自己和子輩門的 Measure()
* 3、UIElement 的 InvalidateArrange() 就是遞歸調用自己和子輩門的 Arrange()
* 
* 一個通過 uwp 自帶控制項說明 layout 的示例,請參見:/Controls/BaseControl/UIElementDemo/LayoutDemo.xaml.cs
*/

Controls/CustomControl/Demo2.xaml

<Page
    x:Class="Windows10.Controls.CustomControl.Demo2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Controls.CustomControl"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    
    xmlns:myControls="using:MyControls">

    <Grid Background="Transparent">
        <StackPanel Margin="10 0 10 10">

            <!--
                演示元素的 Layout 系統
                本例所用到的自定義控制項請參看:MyControls/MyControl2.cs
            -->
            <myControls:MyControl2 Margin="5" Background="Orange" HorizontalAlignment="Left" Width="800">
                <myControls:MyControl2.Children>
                    <TextBlock Text="aaaaaaaa" Margin="5" />
                    <TextBlock Text="bbbbbbbb" Margin="5" />
                    <TextBlock Text="cccccccc" Margin="5" />
                    <TextBlock Text="dddddddd" Margin="5" />
                </myControls:MyControl2.Children>
            </myControls:MyControl2>
            
        </StackPanel>
    </Grid>
</Page>

Controls/CustomControl/Demo2.xaml.cs

/*
 * 本例用於演示元素的 Layout 系統
 */

using Windows.UI.Xaml.Controls;

namespace Windows10.Controls.CustomControl
{
    public sealed partial class Demo2 : Page
    {
        public Demo2()
        {
            this.InitializeComponent();
        }
    }
}


2、演示自定義控制項的控制項模板和事件處理的相關知識點
/MyControls/themes/MyControl3.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    
    xmlns:local="using:MyControls">

    <Style TargetType="local:MyControl3">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:MyControl3">

                    <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                        <StackPanel>
                            <TextBlock Name="textBlock" Foreground="White" FontSize="24" />
                        </StackPanel>

                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />

                                <VisualState x:Name="PointerOver">
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="Green" />
                                    </Storyboard>
                                </VisualState>

                                <VisualStateGroup.Transitions>
                                    <VisualTransition To="PointerOver" GeneratedDuration="0:0:1">
                                        <VisualTransition.GeneratedEasingFunction>
                                            <ElasticEase EasingMode="EaseInOut" />
                                        </VisualTransition.GeneratedEasingFunction>
                                    </VisualTransition>
                                </VisualStateGroup.Transitions>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Border>
                    
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
</ResourceDictionary>

/MyControls/MyControl3.cs

/*
 * 開發一個自定義控制項,用於演示控制項模板和事件處理的相關知識點
 */

using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Input;

namespace MyControls
{
    /// <summary>
    /// 自定義控制項
    /// </summary>
    public sealed class MyControl3 : Control
    {
        public MyControl3()
        {
            this.DefaultStyleKey = typeof(MyControl3);
        }

        // ApplyTemplate() - 強制載入控制項模板,一般不用調用(因為控制項模板會自動載入)。有一種使用場景是:當父控制項應用控制項模板時要求子控制項必須先應用控制項模板以便父控制項使用時,則可以先調用子控制項的此方法
        // GetTemplateChild() - 查找控制項模板中的指定名字的元素
        // override OnApplyTemplate() - 應用控制項模板時調用
        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            TextBlock textBlock = (TextBlock)GetTemplateChild("textBlock");
            if (this.Background is SolidColorBrush)
            {
                textBlock.Text = $"background: {((SolidColorBrush)this.Background).Color}";
            }

            VisualStateManager.GoToState(this, "Normal", false);
        }

        // override GoToElementStateCore() - VisualState 轉換時調用(此方法僅在自定義 ContentPresenter 並將其應用於 GridView 或 ListView 的 ItemContainerStyle 時才會被調用)
        //     參見:/Controls/CollectionControl/ItemsControlDemo/MyItemPresenter.cs
        protected override bool GoToElementStateCore(string stateName, bool useTransitions)
        {
            return base.GoToElementStateCore(stateName, useTransitions);
        }


        // 在 Control 中有很多可 override 的事件處理方法,詳見文檔
        protected override void OnPointerEntered(PointerRoutedEventArgs e)
        {
            VisualStateManager.GoToState(this, "PointerOver", true);
        }

        protected override void OnPointerExited(PointerRoutedEventArgs e)
        {
            VisualStateManager.GoToState(this, "Normal", false);
        }
    }
}

Controls/CustomControl/Demo3.xaml

<Page
    x:Class="Windows10.Controls.CustomControl.Demo3"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Controls.CustomControl"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    
    xmlns:myControls="using:MyControls">

    <Grid Background="Transparent">
        <StackPanel Margin="10 0 10 10">

            <!--
                演示自定義控制項的控制項模板和事件處理的相關知識點
                本例所用到的自定義控制項請參看:MyControls/MyControl3.cs
            -->
            <myControls:MyControl3 Background="Blue" BorderBrush="Yellow" BorderThickness="1" HorizontalAlignment="Left" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

Controls/CustomControl/Demo3.xaml.cs

/*
 * 本例用於演示自定義控制項的控制項模板和事件處理的相關知識點
 */

using Windows.UI.Xaml.Controls;

namespace Windows10.Controls.CustomControl
{
    public sealed partial class Demo3 : Page
    {
        public Demo3()
        {
            this.InitializeComponent();
        }
    }
}



OK
[源碼下載]


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

-Advertisement-
Play Games
更多相關文章
  • 首先,找齊Spring框架中IoC功能、aop功能、JdbcTemplate功能所需的jar包,當前13個Jar包 1、Spring壓縮包中的四個核心JAR包,實現IoC控制反轉的根據xml配置文件或註解生成對象 beans 、context、core 和expression 下載地址: https ...
  • Part VII. Spring Cloud Sleuth 46. Introduction Spring Cloud Sleuth為Spring Cloud實現了分散式的跟蹤解決方案 46.1 Terminology Spring Cloud Sleuth借用了Dapper的術語 Span: 基本 ...
  • 相信各位都在在網上買過東西吧?那麼今天我的主題就是寫個線上購物系統,是不可能的,哈哈(後期確實有這個項目),那麼購物都填寫過快遞地址吧?然後網上查個地址都有地址管理吧? 要求: 1.列印出省、市、縣等多級目錄 2.每一級可以返回到上一級,第一級不能再往上返回 3.可以隨時退出系統 分析: 1.簡單的 ...
  • 使用fmsb包繪製雷達圖 {r} library("fmsb") radarfig ...
  • 1.解釋器路徑 2.編碼 1.ascill 00000000 (8個位表示) 缺點:表示不了英文 2.unicode 0000000000000000+ (至少16位表示) 缺點:消耗記憶體,當表示位不需要16位以上,造成多餘記憶體消耗 Python3 無需關註 Python2 每個文件中只要出現中文, ...
  • [TOC] 一、簡介 java中的日期處理一直是個問題,沒有很好的方式去處理,所以才有第三方框架的位置比如joda。 文章主要對java日期處理的詳解,用1.8可以不用joda。 1. 相關概念 首先我們對一些基本的概念做一些介紹,其中可以將GMT和UTC表示時刻大小等同。 1.1 UT時間 UT反 ...
  • 一、簡介 JavaBean組件是一些可移植、可重用並可組裝到應用程式中的Java類,類必須是具體的和公共的。 符合下列設計規則的任何Java類均是以JavaBean: 1.對數據類型“protype”的每個可讀屬性,Bean下必須有下麵簽名的一個方法:public proptype getPrope ...
  • 1 import java.util.HashMap; 2 import java.util.Iterator; 3 import java.util.Map; 4 5 public class TestMap { 6 public static void main(String[] args) {... ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...