[WPF自定義控制項] 開始一個自定義控制項庫項目

来源:https://www.cnblogs.com/dino623/archive/2019/05/13/CustomControLibrary.html
-Advertisement-
Play Games

1. 目標 我實現了一個自定義控制項庫,並且打算用這個控制項庫作例子寫一些博客。這個控制項庫主要目標是用於教學,希望通過這些博客初學者可以學會為自己或公司創建自定義控制項,並且對WPF有更深入的瞭解。 控制項庫已放在 "Github" 上,並且也以發佈到 "NuGet" 。 現階段我的目標是實現一些簡單的控制項 ...


1. 目標

我實現了一個自定義控制項庫,並且打算用這個控制項庫作例子寫一些博客。這個控制項庫主要目標是用於教學,希望通過這些博客初學者可以學會為自己或公司創建自定義控制項,並且對WPF有更深入的瞭解。

控制項庫已放在Github上,並且也以發佈到NuGet

現階段我的目標是實現一些簡單的控制項,由於我並不是打算重覆造輪子,所以我會挑些Extended Wpf Toolkit沒有的功能實現,之後再根據常用的UI模式慢慢增加各類控制項和工具。(我一直在用Extended Wpf Toolkit,作為免費開源的控制項庫十分好用。)

因為自己很少通過VisualStudio的Toolbox添加控制項,所以暫時不考慮添加工具箱支持,如有需要可以參考這篇文章

要創建一個自定義控制項庫只需要在VisualStudio中新建項目並選擇“WPF 自定義控制項庫”,但創建一個項目還有很多瑣碎的需要考慮的地方,這篇文章主要介紹創建一個控制項庫項目需要考慮的內容。

2. 命名

萬事起頭難,最難的就是命名,控制項庫的命名也煩惱了我很久。

2.1 品牌名

如果是公司的項目,直接用公司名+產品名的組合就可以,但個人的項目就要另外考慮品牌名了。

品牌名有很多地方要考慮,例如不能使用帶有貶義的名稱。有涉及外觀印象的詞也要慎用,如Aqua,給人印象就是水的、藍色的,如果以後要為控制項庫設計紅色的主題就會很尷尬。諾基亞當年選擇Lumia作為品牌連發音都有考慮到:

“在1980年全球只有10,000左右的註冊科技商標,而如今光在美國,就有超過30萬這樣的註冊商標。”克裡斯說道,為此候選名單也從最初的200個一下銳減到為數不多的幾個幸存者身上。
精通各地方言(84種語言)的語言學家們圍繞這些為數不多的幾個幸存者們開始工作,剔除其中某些會產生歧義的單詞,併排除帶有在某些國家很難發音的字母如J,LR和V,和在某些語言中不存在的字母(如在波蘭語中沒有的Q)的單詞,以確保全球絕大多數國家和地區人民都能流暢的說出這一名稱。

雖然只是個控制項庫而已不需要考慮這麼多,但容易發音還是很重要的,最後我選了“kino”,沒什麼意義,只是簡短好讀而已。

2.2 程式集名稱

上面提到的Extended Wpf Toolkit,程式集的名稱是Xceed.Wpf.Toolkit;而WindowsCommunityToolkit的程式集名稱是Microsoft.Toolkit。對這些著名控制項庫來說名稱和程式集的名稱不一致帶來的影響應該不大,但我還是傾向控制項庫的名稱和程式集的名稱一致比較好,畢竟知名度不高的情況下,或者公司內部項目多的情況下很容易產生混亂。

《.NET設計規範:約定、慣用法與模式》這本書里提到:

  • 要用公司名稱作為名字控制項的首碼,這樣可以避免與另一家公司使用相同的名字。
  • 要用穩定的、與版本無關的產品名稱作為名字空間的第二層。

那麼參考Extended Wpf Toolkit的習慣,程式集的名稱應該就是Kino.Wpf.Toolkit。考慮到如果以後可能還需要實現別的類庫,如Kino.Uwp.Toolkit,而這兩個控制項庫共同引用一個基礎類庫的話,那這個基礎類庫不管是叫Kino.Wpf還是Kino.Uwp都比較尷尬。所以最後還是決定Kino.Tookit.Wpf這樣的順序。

複雜的控制項,如DataGrid可以單獨一個程式集(參考Microsoft.Toolkit.Uwp.UI.Controls.DataGrid),但我沒打算做到這麼複雜,目前一個程式集就夠了。

3. 目錄結構

我習慣為每一個(或每一組)控制項單獨建立一個目錄,並且將各個控制項的資源文件分開存放,再在Generic.xaml中合併它們。具體可以參考WindowsCommunityToolkit的做法:


<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/HamburgerMenu/HamburgerMenu.xaml" />
        <ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/HeaderedContentControl/HeaderedContentControl.xaml" />
        <ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/HeaderedItemsControl/HeaderedItemsControl.xaml" />
        <ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/RangeSelector/RangeSelector.xaml" />
        <ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/SlidableListItem/SlidableListItem.xaml" />
        <ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/ImageEx/ImageEx.xaml" />
        <ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/ImageEx/RoundImageEx.xaml" />
        <ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/HeaderedTextBlock/HeaderedTextBlock.xaml" />
        <ResourceDictionary Source="ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/InfiniteCanvas/InfiniteCanvas.xaml" />
        …     
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

其它:

  • Common目錄,工具類放在這個目錄;
  • Converters目錄,實現IValueConverter介面的類都放在這個目錄;
  • Assets及Assets/Images,存放圖片等資源;

4. 命名空間

由於不打算把自定義控制項庫做得太複雜,目前所有控制項都只使用Kino.Toolkit.Wpf這個命名空間。將來如果有一些高級特性或實驗性質的控制項,可以按照Wpf的慣例放在Kino.Toolkit.Wpf.Primitives裡面。

更進一步的,可以添加如下代碼指定XAML中的命名空間:

[assembly: XmlnsPrefix("https://github.com/DinoChan/Kino.Toolkit.Wpf", "kino")]
[assembly: XmlnsDefinition("https://github.com/DinoChan/Kino.Toolkit.Wpf", "Kino.Toolkit.Wpf")]
[assembly: XmlnsDefinition("https://github.com/DinoChan/Kino.Toolkit.Wpf", "Kino.Toolkit.Wpf.Primitives")]

然後在XAML中可以這樣引用:

xmlns:kino="https://github.com/DinoChan/Kino.Toolkit.Wpf"

這樣做的好處是可以忽略真實的命名空間,便於以後修改命名空間或API升級。

5. 版本號

程式集的版本號格式如下:
<主版本>.<次版本>.<生成號>.<修訂版本>

不過平時我都沒用到“修訂版本”,只使用前三個。

Kino.Toolkit.Wpf則大致遵循語義化版本控制

SemVer 的最基本方法是 3 組件格式 MAJOR.MINOR.PATCH,其中:

  • 進行不相容的 API 更改時,MAJOR 將會增加
  • 以後向相容方式添加功能時,MINOR 將會增加
  • 進行後向相容 bug 修複時,PATCH 將會增加

存在多處更改時,單個更改影響的最高級別元素會遞增,並將隨後的元素重置為零。 例如,當 MAJOR 遞增時,MINORPATCH 將重置為零。 當 MINOR 遞增時,PATCH 將重置為零,而 MAJOR 保持不變。

有些人喜歡用日期作為版本號,如“2019.01.01”,這樣也有它的好處,而且很多時候外部版本和內部版本不是一回事。

6 .NET Framework版本

如果只是為了自己或公司創建自定義控制項庫,當然是根據實際用到的.NET Framework版本選擇自定義控制項庫的版本。就我目前情況來看,我選擇了4.5。

7. 代碼規範

基本上遵循《.NET設計規範:約定、慣用法與模式》及.Net Core的規範,並且使用FxCop及EditorConfig協助規範代碼,參考WindowsCommunityToolkit的設定(但還是有些區別,例如花括弧等;後來就越做越多區別)。一些移植過來的代碼會使用SuppressMessage禁止顯示警告。

8. 實現原則

我希望儘可能簡單的實現一些控制項,通過20%的代碼解決80%的問題;我更傾向於介紹一種解決問題的思路,而不是提供一個包羅萬象、面面俱到的成品。而且更複雜的問題通常都是業務上的需求,保持代碼簡單更方便其他人修改我的代碼並靈活使用。

由於ControlTemplate是很符合開放封閉原則的實現,所以能用ControlTemplate解決的自定義問題我都儘可能留給ControlTemplate解決,而不是通過添加大量屬性。

以我的經驗來說,添加新功能很容易,移除舊功能會被人打,新功能的添加一定要謹慎。

因為代碼總是在WPF、Silverlight、UWP之間移植來移植去,所以我一直更傾向於使用相容性較好的方案,例如如果使用VisualState的工作量和ControlTemplate.Triggers差不多我就會使用VisualState實現(不過通常ControlTemplate.Triggers都會簡單很多)。

不會添加在操作上有“獨特創意”的控制項。

9. 結語

Kino.Toolkit.Wpf的初衷畢竟是自己用及教學,沒有通過充分的測試,如果發現嚴重的Bug請協助我修複。

按道理所有控制項應該都不會拒絕MVVM,不過Sample裡面沒有用到MVVM模式,如果發現對MVVM不夠友好的部分請告知。

示例代碼沒有使用MVVM模式,這是因為對控制項的示例來說MVVM並不是那麼直觀,一般WPF的教材也都是使用CodeBehind的方式。

最後提一句,對於太過複雜的控制項,能讓公司花錢買的就儘量花錢買。

10. 引用

Github
NuGet


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

-Advertisement-
Play Games
更多相關文章
  • leepcode 作業詳解 1、給定一個整數數組,判斷是否存在重覆元素。如果任何值在數組中出現至少兩次,函數返回 true。如果數組中每個元素都不相同,則返回 false。 正確解答 第一次用字典去解題,出現bug,雖然在pycharm裡面代碼運行正常,但是leepcode顯示錯誤。 2、給定一個整 ...
  • 引入依賴: 啟動類上添加@EnableFeignClients註解: 寫調用介面: 直接@Autowired註入服務調用介面: 底層使用了動態代理,對介面進行了實現。 並且封裝了RestTemplate遠程調用的代碼。 測試: 搞定~ 補充知識點: ...
  • 力扣題目彙總 1.兩數之和 1.題目描述 給定一個整數數組 和一個目標值 ,請你在該數組中找出和為目標值的那 兩個 整數,並返回他們的數組下標。 你可以假設每種輸入只會對應一個答案。但是,你不能重覆利用這個數組中同樣的元素。 示例: 2.解答 2.迴文數 1題目描述 示例 1: 示例 2: 示例 3 ...
  • 文/開源智造聯合創始人老楊 本文來自《OdooERP系統部署架構指南》的試讀章節。書籍尚未出版,請勿轉載。歡迎您反饋閱讀意見。 從web瀏覽器到PostgreSQL,多層與其他層交互以處理數據 單伺服器架構 易於理解和部署,這是最常見的情況。一個實例或多個實例 多伺服器架構 更難部署和維護,需要更高 ...
  • @Configuration : 配置類 == 配置文件,告訴Spring這是一個配置類@ComponentScan(value="com.atguigu",excludeFilters = { @Filter(type=FilterType.ANNOTATION,classes={Controll ...
  • [TOC] Outline clip_by_value relu clip_by_norm gradient clipping clip_by_value relu clip_by_norm 縮放時不改變梯度方向 gradient clipping Gradient Exploding or van ...
  • [TOC] RabbitMQ 特點 RabbitMQ 相較於其他消息隊列,有一系列防止消息丟失的措施,擁有強悍的高可用性能,它的吞吐量可能沒有其他消息隊列大,但是其消息的保障性出類拔萃,被廣泛用於金融類業務。與其他消息隊列的比較以及強大的防止消息丟失的能力我們將在後續文章再做介紹。 AMQP 協議 ...
  • 使用RestTemplate遠程調用服務的弊端: Eureka註冊中心: Eureka原理: 搭建Eureka服務 引pom 啟動類: 啟動類上要加上@EnableEurekaServer註解: 配置文件中設置埠號: 配置註冊地址: 配置服務名稱: 配置ip地址: 控制面板信息: ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...