UWP開發入門(五)——自定義Panel

来源:http://www.cnblogs.com/manupstairs/archive/2016/01/10/5119713.html
-Advertisement-
Play Games

各位好,終於講到自定義Panel了。當系統自帶的幾個Panel比如Gird,StackPanel,RelativePanel不能滿足我們的特定要求時(其實不常見啦),自定義Panel就顯得非常必要,而且因為是針對性的處理,效果也會非常好。更何況自定義Panel其實並不複雜,今天俺們就來學習一下。.....


  各位好,終於講到自定義Panel了。當系統自帶的幾個Panel比如GirdStackPanelRelativePanel不能滿足我們的特定要求時(其實不常見啦),自定義Panel就顯得非常必要,而且因為是針對性的處理,效果也會非常好。更何況自定義Panel其實並不複雜,今天俺們就來學習一下。

  記得上一篇自定義CommandBar在增加占位控制項AppBarEmpty時,採用的是通過PageSizeChanged事件中計算頁面Width,減去CommandBar中其他控制項Width後再賦值WidthAppBarEmpty的方法。就可行性而言是絕對沒問題的,代碼複雜度也很低,不失為一個好方法。但是復用性不太好,需要在每個Page都寫上一小段代碼。而我們的初衷是希望AppBarEmpty能夠自動撐開,計算自身所需的Width

  遇到的困難來自StackPanel這個控制項,StackPanel在計算自身所需空間時,會非常吝嗇按children元素所需的最小尺寸來申請。就好比申請經費時按最下限申請,這種精神ZF部門應該學習,而公司組織TeamBuilding就應該排斥……)。說到這裡,本篇的主題有了,就是通過自定義一個StackPanelEx來實現讓AppBarEmpty自動撐開的效果。

  前面說了,自定義Panel其實並不複雜。只有兩個方法需要override

        //
        // Summary:(根據子元素測量控制項本身需要的空間)
        //     Provides the behavior for the Measure pass of the layout cycle. Classes can override
        //     this method to define their own Measure pass behavior.
        //
        // Parameters:
        //   availableSize:(控制項本身的可用空間。如指定無窮大值,表示控制項的大小將調整為內容的可用大小)
        //     The available size that this object can give to child objects. Infinity can be
        //     specified as a value to indicate that the object will size to whatever content
        //     is available.
        //
        // Returns:(控制項根據子元素大小計算得出的所需大小)
        //     The size that this object determines it needs during layout, based on its calculations
        //     of the allocated sizes for child objects or based on other considerations such
        //     as a fixed container size.
        protected virtual Size MeasureOverride(Size availableSize);
        //
        // Summary:(根據上面測量的結果,來對子元素進行佈局)
        //     Provides the behavior for the Arrange pass of layout. Classes can override this
        //     method to define their own Arrange pass behavior.
        //
        // Parameters:
        //   finalSize:(控制項用來排列自身及其子元素的最終確定的空間)
        //     The final area within the parent that this object should use to arrange itself
        //     and its children.
        //
        // Returns:(使用的實際大小)
        //     The actual size that is used after the element is arranged in layout.
        protected virtual Size ArrangeOverride(Size finalSize);

  聽上去是不是挺繞的?我們來看StackPanelEx的實際代碼:

    public class StackPanelEx : Panel
    {
        protected override Size MeasureOverride(Size availableSize)
        {
         double height = 0;
            foreach (var child in Children)
            {
                // Tell the child control to determine the size needed
                child.Measure(availableSize);
                height = child.DesiredSize.Height > height ? child.DesiredSize.Height : height;
            }

            return new Size(availableSize.Width,height);
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            int count = Children.Count(_ => _ is AppBarEmpty2);
            double totalLength = Children.Where(_ => _ is AppBarEmpty2 == false).Sum(_ => (_ as FrameworkElement).Width);
            var emptyWidth = (finalSize.Width - totalLength) / count;

            double x = 0;
            foreach (var child in Children)
            {
                if (child is AppBarEmpty2)
                {
                    child.Arrange(new Rect(x, 0, emptyWidth, 0));
                    x += emptyWidth;
                }
                else
                {
                    child.Arrange(new Rect(x, 0, child.DesiredSize.Width, child.DesiredSize.Height));
                    x += child.DesiredSize.Width;
                }
            }
            return finalSize;
        }
    }

  簡單解釋一下,首先在MeasureOverride方法里,告訴每個子元素(這裡是AppBarButtonAppBarEmpty2)去算自己需要多少空間,一會要分地了。然後直接告訴上頭,Width我全要了,Height按我們村裡最高的人給就行了。

  緊接著到了ArrangeOverride方法,上級領導比較大方,告訴該控制項Width全給你,還有你Height要的太少,拖了上級Panel的後腿,多給一些Height免得擠到同級的其他控制項……

  然後村長及開始分地了。AppBarButton就按他自己申請的給,AppBarEmpty2感覺是村長親戚,剩下的Width全給他們家承包了……

  最後向上頭彙報一下分地的情況,這事就算完了。

  AppBarEmpty2還是沒變,和上次一樣。

    public class AppBarEmpty2 : FrameworkElement, ICommandBarElement
    {
        public bool IsCompact { get; set; }
    }

  既然新的StackPanelEx寫好了,就該替換CommandBar原有的StackPanel,找到CommandBar模板中關於PrimaryItemsControl的部分

                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="Auto"/>
                                    </Grid.ColumnDefinitions>
                                    <ContentControl x:Name="ContentControl" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsTabStop="False" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                    <ItemsControl x:Name="PrimaryItemsControl" Grid.Column="0" 
                                                  HorizontalAlignment="Stretch"  IsTabStop="False" MinHeight="{ThemeResource AppBarThemeMinHeight}">
                                        <ItemsControl.ItemsPanel>
                                            <ItemsPanelTemplate>
                                                <!--<StackPanel Orientation="Horizontal"/>-->
                                                <local:StackPanelEx ></local:StackPanelEx>
                                            </ItemsPanelTemplate>
                                        </ItemsControl.ItemsPanel>
                                    </ItemsControl>
                                </Grid>

  ItemsPanelTemplate中的StackPanel替換成StackPanelEx,同時將ItemsControlHorizontalAlignment="Right"改成HorizontalAlignment="Stretch",大功告成,再來看一下Page中的XAML部分:

       <CommandBar x:Name="commandBar" Grid.Row="3" Style="{StaticResource CommandBarStyle2}" >
            <AppBarButton x:Name="appbarButton" Icon="Accept" Label="fdsfdsf" ></AppBarButton>
            <local:AppBarEmpty2  ></local:AppBarEmpty2>
            <AppBarButton Icon="Accept" Label="fdsfdsf"></AppBarButton>
            <local:AppBarEmpty2  ></local:AppBarEmpty2>
            <AppBarButton Icon="Accept" Label="fdsfdsf" ></AppBarButton>
        </CommandBar>

  是不是非常的清爽,再也不用去寫什麼SizeChanged事件了。實際效果如下圖:

 

 

 

 

 

 


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

-Advertisement-
Play Games
更多相關文章
  • 提要16 讀取轉換流17 寫入轉換流18 流操作規律-119 流操作規律-220 改變標準輸入輸出設備21 異常的日誌信息22 系統信息16 讀取轉換流字元流體系中的InputStreamReader,是位元組流通向字元流的橋梁:它使用指定的charset讀取位元組並將其解碼為字元。它使用的字元集可以由...
  • 問題描述 若一個數(首位不為零)從左向右讀與從右向左讀都一樣,我們就將其稱之為迴文數。 例如:給定一個10進位數56,將56加65(即把56從右向左讀),得到121是一個迴文數。 又如:對於10進位數87: STEP1:87+78 = 165 STEP2:165+561 = 726 STE...
  • Jdk:Java程式設計語言、Java虛擬機、Java API類庫。Jdk是用於支持Java程式開發的最小環境。Jre:Java API類庫中的Java SE API子集、Java虛擬機。Jre是支持Java程式運行的標準環境。Program Counter Register:較小的記憶體空間,可以看...
  • dt.ToString();//2005-11-5 13:47:04 dt.AddYears(1).ToString();//2006-11-5 13:47:04 dt.AddDays(1.1).ToString();//2005-11-6 16:11:04 dt.AddHours(1.1).ToS...
  • 2:Set集合(理解) (1)Set集合的特點 無序,唯一 (2)HashSet集合(掌握) A:底層數據結構是哈希表(是一個元素為鏈表的數組) B:哈希表底層依賴兩個方法:hashCode()和equals() 執行順序: 首先比較哈希值是否相同 相同:繼續執行equals()方法 返回true:...
  • 原文:http://www.cnblogs.com/FreeDong/archive/2013/07/31/3227638.html一、委托調用方式1. 最原始版本:delegate string PlusStringHandle(string x, string y);class Program{...
  • 首先是存儲過程,只取出我需要的那段數據,如果頁數超過數據總數,自動返回最後一頁的紀錄:set ANSI_NULLS ONset QUOTED_IDENTIFIER ONGO-- =============================================-- Author: Clear...
  • //c datetime 格式化DateTime dt = DateTime.Now;Label1.Text = dt.ToString();//2005-11-5 13:21:25Label2.Text = dt.ToFileTime().ToString();//1277564168599128...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...