在Winform界面使用自定義用戶控制項及TabelPanel和StackPanel佈局控制項

来源:https://www.cnblogs.com/wuhuacong/archive/2020/01/17/12201665.html
-Advertisement-
Play Games

在很多時候,我們做一些非常規化的界面的時候,往往需要創建一些用戶控制項,在其中繪製好一些基礎的界面塊,作為後續重覆使用的一個單元,用戶控制項同時也可以封裝處理一些簡單的邏輯。在開發Winform各種類型項目,我都時不時需要定製一些特殊的用戶控制項,以方便在界面模塊中反覆使用。我們一般是在自定義的用戶控制項里... ...


在很多時候,我們做一些非常規化的界面的時候,往往需要創建一些用戶控制項,在其中繪製好一些基礎的界面塊,作為後續重覆使用的一個單元,用戶控制項同時也可以封裝處理一些簡單的邏輯。在開發Winform各種類型項目,我都時不時需要定製一些特殊的用戶控制項,以方便在界面模塊中反覆使用。我們一般是在自定義的用戶控制項裡面,添加各種各樣的界面控制項元素,或者封裝一些特殊的函數處理共外部調用等。本篇隨筆主要介紹基於DevExpress的Winform開發經驗,介紹一個類似看板信息的用戶控制項,併在TabelLayout和StackLayout佈局控制項中進行展示。

1、用戶控制項界面的處理

 在偶爾的一個場合下,看到一個牙醫管家的軟體界面做的非常不錯,其中有一個預約列表的界面感覺非常好,如下界面所示。

 

 其中它的每個用戶信息列表裡面,都是一個綜合信息的展示,非常直觀,估計應該是用戶自定義控制項做的。

在其中裡面,有不同的字體,各式圖標,以及內容的信息展示, 這個我在DevExpress的列表控制項裡面,沒有看到可以如此定義列表內容的,在DevExpress的GridView裡面有一個看板模板的定義有點接近,但是試了一下,可調性不好,於是放棄尋求其他接近方案,玩遍DevExpress的控制項後,發現最好的方式應該是自定義用戶控制項的方式來解決這個界面問題。

花了一點時間,製作了一個用戶控制項,在其中添加一個LayoutControl方便控制佈局,添加一些標簽以及設置了一些圖標,得到下圖所示。

 

  左側的顏色條由於使用Group控制項,因此寬度暫時無法調整,如果介意大小,我們可以在其中在創建一個LayoutControl,然後在其中方式內容即可。

我們改變佈局,然後添加一個顏色塊,得到類似界面如下所示。

 

我們來定義一下用戶控制項的源碼部分,修改其中源碼,增加對應的屬性,方便動態設置用戶控制項的相關屬性,如顏色塊,項目背景色,以及綁定的對象信息等內容。

 

 然後在界面載入完畢後,設置對應的信息和顏色信息,如下代碼所示。

        /// <summary>
        /// 視窗載入事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserItemControl_Load(object sender, EventArgs e)
        {
            BindData();
            RefreshColor();
        }

        /// <summary>
        /// 根據用戶定義信息,顯示不同的內容
        /// </summary>
        private void BindData()
        {
            if(this.UserItemInfo != null)
            {
                var info = this.UserItemInfo;
                this.lblCustomerName.Text = info.CustomerName;
                this.lblMobile.Text = info.Mobile;
                this.lblReceiver.Text = info.Receiver;
                this.lblRecordDate.Text = info.RecordDate;
                this.lblRecordNo.Text = info.RecordNo;
                this.lblDealType.Text = "";
                this.lblStar.ImageOptions.ImageIndex = GetStarImageIndex(info.Stars);
                if (!info.IsVip)
                {
                    this.lblVip.Visibility = LayoutVisibility.Never;
                }
            }
        }

        /// <summary>
        /// 刷新背景色
        /// </summary>
        private void RefreshColor()
        {
            if (ItemBlockColor != Color.Empty)
            {
                this.itemColor.AppearanceItemCaption.BackColor = ItemBlockColor;
            }
            if (ItemBackColor != Color.Empty)
            {
                layoutControl1.BackColor = ItemBackColor;
            }
        }

但我們滑鼠浮動在項目上或者離開的時候,或者單擊某項的時候,我們變換下顏色,方便區分顯示。

        private void layoutControl1_MouseLeave(object sender, EventArgs e)
        {
            if (!this.IsSelected)
            {
                this.layoutControl1.ResetBackColor();
            }
        }

        private void layoutControl1_MouseEnter(object sender, EventArgs e)
        {
            if (!this.IsSelected)
                this.layoutControl1.BackColor = Color.FromArgb(192, 255, 192);
        }

        private void layoutControl1_Click(object sender, EventArgs e)
        {
            this.IsSelected = true;
            OnItemClick?.Invoke(this, e);
        }

完成這些後,我們需要在窗體上對內容進行初始化。

最後我們看看界面的效果如下所示

 或者下麵這樣的界面佈局。

如果嫌棄邊框紅色不好看,我們 可以修改邊框為灰色調一點的,這樣總體看起來效果如下所示。

 

 得到和我們最終需要的界面很接近了。

一般除了懸浮滑鼠顏色變化外,控制項單擊後,我們會設置不同的背景色,以示區分。

        /// <summary>
        /// 是否選中節點
        /// </summary>
        public bool IsSelected
        {
            get
            {
                return m_IsSelected;
            }
            set
            {
                m_IsSelected = value;

                this.ItemBackColor = value ? Color.FromArgb(255, 255, 192) : Color.Transparent;
                this.RefreshColor();
            }
        }

一般列表界面中,我們除了支持滑鼠移動、單擊變色的效果外,我們還希望支持通過鍵盤箭頭上下鍵進行上下瀏覽項目。我們如果需要使用鍵盤的按鍵,需要設置窗體的KeyPreview屬性為True,

然後跟蹤按鍵的事件即可,如下所示。

            this.KeyPreview = true;
            this.KeyUp += FrmKanBan_KeyUp;

按鍵事件捕捉處理如下所示,主要就是判斷選中的用戶控制項,並對面板的子控制項的選中效果進行處理。

        private void FrmKanBan_KeyUp(object sender, KeyEventArgs e)
        {
            //單擊滑鼠或者切換按鍵,會觸發用戶控制項獲得selectItem對象,可以進行箭頭上下移動
            if (selectItem != null)
            {
                var panel = selectItem.Parent;
                if (panel != null)
                {
                    //獲取操作項的索引值
                    int oldIndex = panel.Controls.IndexOf(selectItem);
                    if (e.KeyCode == Keys.Up)
                    {
                        if (oldIndex > 0)
                        {
                            //通過序號獲得新的控制項,並單擊它觸發選擇事件
                            var newCtrl = panel.Controls[oldIndex - 1];
                            Item_OnItemClick(newCtrl, new EventArgs());
                        }
                    }
                    else if (e.KeyCode == Keys.Down)
                    {
                        if (oldIndex < (panel.Controls.Count - 1))
                        {
                            //通過序號獲得新的控制項,並單擊它觸發選擇事件
                            var newCtrl = panel.Controls[oldIndex + 1];
                            Item_OnItemClick(newCtrl, new EventArgs());
                        }
                    }
                }
            }
        }

界面中用戶控制項的切換選中效果,需要先清空之前所有的選擇,然後在設置新的選中控制項,所以還需要對控制項觸發單擊事件進行處理,如下所示。

        /// <summary>
        /// 選中的用戶控制項對象實例
        /// </summary>
        UserItemControl selectItem = null;
        /// <summary>
        /// 單擊用戶控制項,觸發清除所有標記後,再次設置選中的項目標記
        /// </summary>
        private void Item_OnItemClick(object sender, EventArgs e)
        {
            //清空所有控制項的選中標記
            var panel = (PanelControl)((Control)sender).Parent;
            foreach (Control ctrl in panel.Controls)
            {
                var item = ctrl as UserItemControl;
                if(item != null)
                {
                    item.IsSelected = false;
                }
            }

            //設置選中控制項
            selectItem = ((UserItemControl)sender);
            selectItem.IsSelected = true;
            this.Text = selectItem.UserItemInfo.CustomerName + "-選中";

            //如果在面板中遮擋,移動滾動條,可以查看到完整用戶控制項界面
            panel.ScrollControlIntoView(selectItem);
        }

如下效果所示。

 

2、TabelLayout和StackLayout佈局控制項的介紹和使用

 我們在做Winform開發的時候,一般知道,微軟傳統Winform的佈局提供兩個控制項,FlowLayoutPanel和TableLayoutPanel,一個是流式佈局,一個是表格佈局,各有各的用處。流式佈局主要就是按照順序挨個放置控制項,表格佈局主要按照表格的定義的行列單元格,嚴格放置控制項,表格單元格控制強度更大,而且控制項具有拉伸效果。

對於DevExpress,我們一般還是傾向於採用它提供給的控制項來做界面,可以很好融合它的皮膚效果,相對於Winform傳統兩個佈局控制項,DevExpress提供了兩個封裝效果相當的控制項佈局StackPanel和 TablePanel,他們的效果實現大同效果,不過調用的介面不同。

 

 對於兩個控制項,我們希望裡面的內容自動出現滾動條,那麼設置屬性AutoScroll 為True即可,如下代碼所示。

panel.AutoScroll = true;

而StackPanel另外需要LayoutDirection,也就是控制項順序展現的方式,如下代碼所示。

panel.LayoutDirection = StackPanelLayoutDirection.TopDown;

使用StackPanel面板來測試展示用戶控制項列表的界面代碼如下所示。

        /// <summary>
        /// 使用StackPanel對用戶控制項佈局進行處理
        /// </summary>
        private void InitPanel(StackPanel panel)
        {
            panel.AutoScroll = true;//面板自動出現滾動條
            panel.LayoutDirection = StackPanelLayoutDirection.TopDown;//從上往下展示
            panel.Controls.Clear();//清空界面

            var list = GetInfoList(); //獲取用戶控制項綁定的對象信息列表
            for (int i = 0; i < list.Count; i++)
            {
                //定義用戶控制項實例
                var item = new UserItemControl();
                item.UserItemInfo = list[i];//綁定對象信息

                item.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                item.ItemBlockColor = colors[i %10]; //變化顏色
                item.OnItemClick += Item_OnItemClick;//觸發選中事件

                panel.Controls.Add(item);
            }
        }

對於表格佈局TablePanel控制項來說,使用初始化控制項的方式也差不多,不過有個別地方註意即可。

        /// <summary>
        /// 使用TablePanel對用戶控制項佈局進行處理
        /// </summary>
        private void InitPanel(TablePanel panel)
        {
            panel.AutoScroll = true;//面板自動出現滾動條
            panel.Controls.Clear();//清空界面
            panel.Rows.Clear();//清空行
            panel.Columns.Clear();//清空列

            //添加列定義(增加一個列即可)
            panel.Columns.Add(new TablePanelColumn(TablePanelEntityStyle.Relative, 55F));
            var list = GetInfoList(); //獲取用戶控制項綁定的對象信息列表
            for (int i = 0; i < list.Count; i++)
            {
                //定義行信息
                panel.Rows.Add(new TablePanelRow(TablePanelEntityStyle.AutoSize, 100F));

                //定義用戶控制項實例
                var item = new UserItemControl();
                item.UserItemInfo = list[i];
                //定義拉伸效果
                item.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
                item.ItemBlockColor = colors[i % 10]; //變化顏色
                item.OnItemClick += Item_OnItemClick;//觸發選中事件

                //先添加控制項到面板集合中
                panel.Controls.Add(item);
                //設置控制項的單元格位置
                panel.SetCell(item, i, 0);
            }

            //添加多一行,確保佈局
            panel.Rows.Add(new TablePanelRow(TablePanelEntityStyle.AutoSize, 100F));
        }

添加控制項的時候,需要註意下麵的代碼,才能正常展示控制項信息,否則無法看到用戶控制項。

                //先添加控制項到面板集合中
                panel.Controls.Add(item);
                //設置控制項的單元格位置
                panel.SetCell(item, i, 0);

最後對比下效果,左邊是TablePanel,右邊是StackPanel展現出來的效果。

 

 以上就是界面如何在DevExpress開發中使用各種用戶控制項進行用戶控制項的創建、以及實現滑鼠進入、移出、單擊的不同效果,以及實現鍵盤上下箭頭按鍵的事件選中效果,並介紹DevExpress中兩個佈局控制項TabelPanel和StackPanel的正常使用,達到展示控制項信息的作用。


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

-Advertisement-
Play Games
更多相關文章
  • 這幾天,對程式重構,主要針對angularjs的綁定: 第一個例子: 下麵是一段html程式: 不管是name或者是ng-model的屬性值,它都有一定規律"StartX"和"EndX" 後面的數字是連續的序號。 我們可以使用ASP.NET MVC的Razor的語法@for來簡化它們: @{ for ...
  • C#實現的Check Password,並根據輸錯密碼的次數分情況鎖定賬戶:如果輸入錯誤3次,登錄賬戶鎖定5分鐘並提示X點X分後重試登錄。如果5分鐘後再次輸入,累計輸入錯誤密碼累計達到5次。則賬戶會被永久鎖定,需聯繫系統管理員進行把資料庫中的輸入錯誤的次數(errorcount)進行清零解鎖才能登陸 ...
  • [TOC] MVC "MVC 維基百科,自由的百科全書" MVC 是軟體工程的一種軟體架構模式,它不是具體的技術,而是一種代碼分層的理念,主要體現了職責分離原則。 M Model 模型 V View 視圖 C Controller 控制器 對 MVC 的誤解及緣由 誤解:頁面視圖 = View ,E ...
  • 簡介 Orleans用起來的確很爽,更爽的是咱們有能監控它的工具。 " OrleansDashboard " 這個工具是一個可視化的Silo監控工具,Silo和Grain的活躍狀態一目瞭然,各個介面的響應速度也可以很清晰的統計到。 安裝 使用NuGet引用 然後修改 的配置,添加Dashboard: ...
  • Teigha中實體旋轉 代碼: using (var trans = database.TransactionManager.StartTransaction()) { Entity ent = trans.GetObject(entityId, OpenMode.ForWrite) asEntit ...
  • 什麼是AutoMapper?AutoMapper是一個簡單的小型庫,用於解決一個看似複雜的問題 - 擺脫將一個對象映射到另一個對象的代碼。這種類型的代碼是相當沉悶和無聊的寫,所以為什麼不發明一個工具來為我們做? 我們來看看在.netcore3.1中怎樣使用AutoMapper9.0。 Profile ...
  • 程式處理存放圖片的幾種方式 我的理解有4個: 1:放在項目本身得文件夾中,直接部署到伺服器上 2:存放在磁碟中,然後資料庫中存放路徑,讀取得時候傳路徑。這個適合小項目 3:將圖片轉換成二進位文件,但是不建議這樣做,因為會給資料庫造成壓力。 4:存放在雲存儲器上,也是在資料庫上存地址,不過是雲地址,使 ...
  • 第一部分:面向對象 封裝 繼承(里氏轉換) 多態第二部分:值類型、引用類型、字元串操作第三部分:集合文件操作第四部分:正則表達式第五部分:XML操作第六部分:委托、事件第七部分:反射。 //存儲著我們當前正在運行的進程//Process[] pro = Process.GetProcesses(); ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...