在Winform開發框架中使用DevExpress的內置圖標資源

来源:https://www.cnblogs.com/wuhuacong/archive/2018/12/10/10095661.html
-Advertisement-
Play Games

在開發Winform程式界面的時候,我們往往會使用一些較好看的圖表,以便能夠為我們的程式界面增色,良好的圖標設置可以讓界面看起來更加美觀舒服,而且也比較容易理解,圖標我們可以通過一些網站獲取各種場景的圖標資源,不過本篇隨筆主要介紹如何利用DevExpress的內置圖標資源來實現界面圖標的設置。 ...


在開發Winform程式界面的時候,我們往往會使用一些較好看的圖表,以便能夠為我們的程式界面增色,良好的圖標設置可以讓界面看起來更加美觀舒服,而且也比較容易理解,圖標我們可以通過一些網站獲取各種場景的圖標資源,不過本篇隨筆主要介紹如何利用DevExpress的內置圖標資源來實現界面圖標的設置。

1、設計時刻的圖標處理

豐富的圖標處理,在菜單、工具欄、樹列表等地方,以及按鈕等地方,都可以使用,而這些我們可以利用DevExpress的內置圖標選擇來減輕我們尋找合適圖標的煩惱。

一些按鈕、工具欄等的圖標設置,一般是固定的,我們往往可以在設計時刻就指定它,這樣我們可以使用本地的圖標,也可以使用DevExpress的內置圖標。而使用DevExpress內置圖標資源的時候,我們可以調出DevExpress的內置圖標選擇框的。

 如下是按鈕添加圖標方式,操作非常簡單,在按鈕的右上角小圖標上單擊一下進入編輯界面,如下所示。

然後選擇Image按鈕,進入圖標選擇界面,選擇內置的DevExpress圖標庫即可,基本上,只要是DevExpress的原生控制項,那麼就可以通過這種內置圖標的對話框進行圖標選擇,非常方便。

 

2、運行時刻的圖標處理

上面的操作是在設計時候,DevExpress設計器給我們提供很多便利選擇內置圖標,而在界面運行時刻,想動態處理界面按鈕圖標,或者樹形菜單的圖標的時候,就沒有這個直接的介面來設置圖標了,而我們框架的菜單往往都是需用動態增加的,因此圖標的設置也是在運行時刻的。如下麵的樹列表中,圖標就是動態指定的。

這些動態的樹形菜單,是在許可權系統裡面動態配置的,菜單的配置界面如下所示。

上面的選擇圖圖標就是我們需要動態設置的圖標,由於圖標資源我們是以圖片形式存儲在對應的記錄裡面的,因此使用起來也是比較方便的,我們在配置的時候,獲取到對應的圖標資源並存儲起來即可。

除了上面可以參考從DevExpress內置圖標資源獲取圖標的方式外

我們還可以選擇我們自己喜歡的圖標資源,也就是從系統圖標文件中選擇自己喜歡的,如下界面所示。

因此我考慮在運行時刻整合兩種不同選擇圖標的方式。

我們先來看看我整合後的圖表選擇界面,如下所示,包含了運行時刻提取DevExpress內置圖標的功能和從系統文件中選擇圖標的功能。

 

 3、運行時刻提取DevExpress內置圖標的功能實現

 首先我們參考設計時刻的界面展示

來設計一個界面來展示圖標信息

 參考原版的界面,設計儘可能貼近即可,另外我們自己加入一個從系統選擇圖標資源的操作。

至於圖標選中後我們返回對應的Image對象給調用者,則通過事件進行處理,以便選中後,即使更新顯示效果。

如下所示,我們定義一個委托和事件。

    /// <summary>
    /// DevExpress圖標和系統圖標選擇窗體
    /// </summary>
    public partial class FrmImageGallery : BaseForm
    {
        /// <summary>
        /// 自定義一個委托處理圖標選擇
        /// </summary>
        public delegate void IconSelectHandlerDelegate(Image image, string name);

        /// <summary>
        /// 圖標選擇的事件
        /// </summary>
        public event IconSelectHandlerDelegate OnIconSelected;

        private DXImageGalleryLoader loader = null;

        public FrmImageGallery()
        {
            InitializeComponent();

            InitDictItem();//初始化
        }      

        /// <summary>
        /// 處理圖標選擇的事件觸發
        /// </summary>
        public virtual void ProcessIconSelected(Image image, string name)
        {
            if (OnIconSelected != null)
            {
                OnIconSelected(image, name);
            }
        }

然後在內置圖標顯示中,如果觸發圖標的單擊,我們就觸發事件,以便讓調用者更新界面顯示,如下代碼所示。

foreach (GalleryItem item in items[key])
{
    item.ItemClick += (s, e) =>
    {
        //選擇處理
        ProcessIconSelected(item.ImageOptions.Image, item.Description);
    };
}

而對於從系統文件載入文件進行顯示圖標的,類似的觸發方式。

        /// <summary>
        /// 從系統資源中載入圖標文件,然後觸發事件進行顯示
        /// </summary>
        private void txtFilePath_Properties_ButtonClick(object sender, ButtonPressedEventArgs e)
        {
            string file = GetIconPath();
            if (!string.IsNullOrEmpty(file))
            {
                this.txtFilePath.Text = file;//記錄文件名
                this.txtEmbedIcon.Image = LoadIcon(file);//顯示圖片
                this.txtEmbedIcon.Size = new System.Drawing.Size(64, 64);

                //返回處理
                ProcessIconSelected(this.txtEmbedIcon.Image, file);
            }
        }

這樣我們在菜單的選擇圖標的時候,就可以觸發事件進行獲取圖表並更新自身了。

        private void btnSelectIcon_Click(object sender, EventArgs e)
        {
            FrmImageGallery dlg = new FrmImageGallery();
            dlg.OnIconSelected += (image, name) =>
            {
                this.txtEmbedIcon.Image = image;
            };
            dlg.ShowDialog();
        }

完成了這些處理,我們再次將焦點放在如何提取並展示DevExpress內置圖標的身上。

 為了獲取圖表資源裡面的分類及大小等信息,我們需要把圖標資源進行一個載入出來,然後讀取裡面的類別和大小、集合等信息。先定義幾個變數來承載這些信息。

        /// <summary>
        /// 圖標分類
        /// </summary>
        public List<string> Categories { get; set; }
        /// <summary>
        /// 圖標集合
        /// </summary>
        public List<string> Collection { get; set; }
        /// <summary>
        /// 圖標尺寸
        /// </summary>
        public List<string> Size { get; set; }

我們知道,DevExpress的圖標資源在程式集DevExpress.Utils.DxImageAssemblyUtil.ImageAssembly裡面,因此我們需要對它進行讀取,並依次對各個資源進行處理。

我們來看看具體的處理代碼,如下所示。

            using (System.Resources.ResourceReader reader = GetResourceReader(DevExpress.Utils.DxImageAssemblyUtil.ImageAssembly))
            {
                System.Collections.IDictionaryEnumerator dict = reader.GetEnumerator();
                while (dict.MoveNext())
                {
                    string key = (string)dict.Key as string;
                    if (!DevExpress.Utils.DxImageAssemblyUtil.ImageProvider.IsBrowsable(key)) continue;
                    if (key.EndsWith(".png", StringComparison.Ordinal))
                    {
                        string reg = @"(?<collection>\S*?)/(?<category>\S*?)/(?<name>\S*)";
                        var collectionItem = CRegex.GetText(key, reg, "collection"); 
                        var categoryItem = CRegex.GetText(key, reg, "category");
                        string sizeReg = @"_(?<size>\S*)\.";
                        var sizeItem = CRegex.GetText(key, sizeReg, "size");

                        if (!this.Collection.Contains(collectionItem))
                        {
                            this.Collection.Add(collectionItem);
                        }
                        if (!this.Categories.Contains(categoryItem))
                        {
                            this.Categories.Add(categoryItem);
                        }
                        if (!this.Size.Contains(sizeItem))
                        {
                            this.Size.Add(sizeItem);
                        }

                        Image image = GetImageFromStream((System.IO.Stream)dict.Value);
                        if (image != null)
                        {
                            var item = new DevExpress.XtraBars.Ribbon.GalleryItem(image, key, key);
                            if (!ImageCollection.ContainsKey(key))
                            {
                                ImageCollection.Add(key, item);
                            }
                        }                        
                    }
                }
            }

其中讀取資源的操作代碼是

GetResourceReader(DevExpress.Utils.DxImageAssemblyUtil.ImageAssembly)

這個代碼它就是從資源裡面進行獲取對應的圖表資源。

        private System.Resources.ResourceReader GetResourceReader(System.Reflection.Assembly imagesAssembly)
        {
            var resources = imagesAssembly.GetManifestResourceNames();
            var imageResources = Array.FindAll(resources, resourceName => resourceName.EndsWith(".resources"));
            if (imageResources.Length != 1)
            {
                throw new Exception("讀取異常");
            }
            return new System.Resources.ResourceReader(imagesAssembly.GetManifestResourceStream(imageResources[0]));
        }

另外,我們根據圖表的文件名結構,我們通過正則表達式來讀取它的對應信息,然後把它的大小、類別、集合信息存儲起來。

    string reg = @"(?<collection>\S*?)/(?<category>\S*?)/(?<name>\S*)";
    var collectionItem = CRegex.GetText(key, reg, "collection"); 
    var categoryItem = CRegex.GetText(key, reg, "category");
    string sizeReg = @"_(?<size>\S*)\.";
    var sizeItem = CRegex.GetText(key, sizeReg, "size");

圖表信息讀取了,我們需要解析它然後存儲起來,把圖標的Image對象放在一個字典類別裡面,方便按照組別進行展示。

    Image image = GetImageFromStream((System.IO.Stream)dict.Value);
    if (image != null)
    {
        var item = new DevExpress.XtraBars.Ribbon.GalleryItem(image, key, key);
        if (!ImageCollection.ContainsKey(key))
        {
            ImageCollection.Add(key, item);
        }
    }      

有了這些資源,我們對它們進行搜索就顯得很方便了,我們如果需要根據文件名或者其他條件進行查詢集合的數據,提供一個通用的方法即可,如下代碼所示。

        /// <summary>
        /// 根據條件獲取集合
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, GalleryItemCollection> Search(List<string> collection, List<string> categories, 
            List<string> size, string fileName = "")
        {
            Dictionary<string, GalleryItemCollection> dict = new Dictionary<string, GalleryItemCollection>();

            GalleryItemCollection list = new GalleryItemCollection();
            foreach (var key in ImageCollection.Keys)
            {
                //使用正則表達式獲取圖標文件名中的集合、類別、大小等信息
                string reg = @"(?<collection>\S*?)/(?<category>\S*?)/(?<name>\S*)";
                var collectionItem = CRegex.GetText(key, reg, "collection");
                var categoryItem = CRegex.GetText(key, reg, "category");
                string sizeReg = @"_(?<size>\S*)\.";
                var sizeItem = CRegex.GetText(key, sizeReg, "size");

                //如果是查詢處理,把記錄放到查詢結果裡面
                if (!string.IsNullOrEmpty(fileName))
                {
                    if(key.Contains(fileName))
                    {
                        list.Add(ImageCollection[key]);
                    }
                    dict["查詢結果"] = list;
                }
                else
                {
                    //如果是集合和列表中包含的,把它們按類別添加到字典裡面
                    if (collection.Contains(collectionItem) && 
                        categories.Contains(categoryItem) && 
                        size.Contains(sizeItem))
                    {
                        if (!dict.ContainsKey(categoryItem))
                        {
                            GalleryItemCollection cateList = new GalleryItemCollection();
                            cateList.Add(ImageCollection[key]);
                            dict[categoryItem] = cateList;
                        }
                        else
                        {
                            GalleryItemCollection cateList = dict[categoryItem];
                            cateList.Add(ImageCollection[key]);
                        }
                    }
                }
            }
            return dict;
        }

這次搜索就直接基於已有的集合ImageCollection 進行搜索的了,不用再次讀取程式集並依次分析它,速度提供不少的。

由於圖表資源的處理是比較耗時的,我們把整個圖標載入的類作為一個靜態的對象緩存起來,這樣下次使用直接從緩存裡面拿,對應的資源也不用重新載入,更好的提高我們重用的效果了,體驗更好了。

    /// <summary>
    /// 圖標庫載入處理
    /// </summary>
    public class DXImageGalleryLoader
    {
        /// <summary>
        /// 圖標字典類別集合
        /// </summary>
        public Dictionary<string, GalleryItem> ImageCollection { get; set; }
        /// <summary>
        /// 圖標分類
        /// </summary>
        public List<string> Categories { get; set; }
        /// <summary>
        /// 圖標集合
        /// </summary>
        public List<string> Collection { get; set; }
        /// <summary>
        /// 圖標尺寸
        /// </summary>
        public List<string> Size { get; set; }

        /// <summary>
        /// 使用緩存處理,獲得對象實例
        /// </summary>
        public static DXImageGalleryLoader Default
        {
            get
            {
                System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod();
                string keyName = string.Format("{0}-{1}", method.DeclaringType.FullName, method.Name);

                var result = MemoryCacheHelper.GetCacheItem<DXImageGalleryLoader>(keyName,
                       delegate () { return new DXImageGalleryLoader().LoadData(); },
                       new TimeSpan(0, 30, 0));//30分鐘過期
                return result;
            }
        }

以上代碼通過

public static DXImageGalleryLoader Default

定義了一個靜態的實例屬性,這樣這個 DXImageGalleryLoader 實例只會在程式第一次使用的時候構建並載入圖片資源,後續都是從緩存裡面讀取,提高響應速度的同時,也會記住上次的選擇界面內容。

以上就是整個功能的處理思路,以及一步步的優化處理,以便實現功能展示的同時,也提高響應速度,最終界面就是我們開始的時候介紹的那樣。

 

單擊或者選中系統圖標後, 需要設置的按鈕或者界面,就會及時更新圖標展示,體驗效果還是非常不錯的。

由於這個界面功能的通用性,我把它作為系統界面基礎模塊,放到了我的框架BaseUIDx裡面,各個系統模塊都可以調用了。


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

-Advertisement-
Play Games
更多相關文章
  • 1. 在微信開放平臺註冊開發者賬號,並有一個審核已通過的網站應用,並獲得相對應的AppID和AppSecret,申請通過登陸後,方可開始接入流程。 2.微信OAuth2.0授權登錄目前支持authorization_code模式,適用於擁有server端的應用授權。該模式整體流程為: 3.實現代碼如 ...
  • 一、單例模式是什麼? 定義:確保一個類僅僅能產生一個實例,並且提供一個全局訪問點來獲取該實例。 二、單例模式怎麼用? 1 class SingleCase 2 { 3 public string Name{get;set;} 4 public static SingleCase mySingle = ...
  • 例:字元串 string str="2,3,5,7,9," 去掉最後一個逗號 ","; 常用的方法: 1.SubString()方法 str=str.SubString(0,str.Length - 1); 2.Remove()方法 str=str.Remove(str.Length-1,1); 3 ...
  • 1.打開visual Studio 2. 通過菜單Edit -->Find and Replace -->Replace In File ,或者使用 ctrl + Shift + H 打開在文件中查找對話框,如下: Find What: 填寫查找語句的地方,可以是入任何查找關鍵字,也可以是正則表達式 ...
  • 最基礎的網頁設計,就是給你一個圖片你做成一個網頁,當然,我的工作是C#,個人網頁的功底不是很高首先先認識一下網頁的一些相關知識: 一般的,現在一個html網頁一般包含html文件,css文件,js文件,img文件這幾個部分css文件,全名叫成疊樣式表稍後會說說,js呢,這個文章暫時先不說現在說說網頁 ...
  • 今天在用到EasyUI 的Tree,TreeGrid,每次轉出這個數據格式非常不爽,就自己寫了段HELPER 輸出到前端: JsonConvert.SerializeObject(TreeDataHelper<T>.GetTreeDataFromList(tList, x1 => x1.Id, x1 ...
  • 1. 首先繼承一個listbox,來獲得按住ctrl鍵時,點擊的item 2 在listbox 的調用處: 獲得listbox 的選中項:SelectedItemsList 3 在mouseleftdown事件裡面添加處理程式 ...
  • 基於Visual Studio .NET2015的單元測試 如果類或者方法沒有用public修飾,會提示錯誤。 l Assert.Inconclusive() 表示一個未驗證的測試 l Assert.AreEqual() 測試指定的值是否相等,如果相等,則測試通過 l AreSame() 用於驗證指 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...