在Winform界面中使用自定義控制項,豐富界面的效果處理

来源:https://www.cnblogs.com/wuhuacong/p/18036358
-Advertisement-
Play Games

我們在《SqlSugar開發框架》中,Winform界面開發部分往往也用到了自定義的用戶控制項,對應一些特殊的界面或者常用到的一些局部界面內容,我們可以使用自定義的用戶控制項來提高界面的統一性,同時也增強了使用的便利性。如我們Winform界面中用到的分頁控制項、附件顯示內容、以及一些公司、部門、菜單的下... ...


我們在《SqlSugar開發框架》中,Winform界面開發部分往往也用到了自定義的用戶控制項,對應一些特殊的界面或者常用到的一些局部界面內容,我們可以使用自定義的用戶控制項來提高界面的統一性,同時也增強了使用的便利性。如我們Winform界面中用到的分頁控制項、附件顯示內容、以及一些公司、部門、菜單的下拉框列表等等,由於重覆多處使用,因此一處封裝多處收益。

1、回顧Winform界面中自定義的用戶控制項的處理場景

其實我的關於Winform的開發隨筆,介紹了不少的控制項使用、以及自定義控制項的使用例子,如隨筆《在Winform界面使用自定義用戶控制項及TabelPanel和StackPanel佈局控制項》中介紹到模仿牙醫管家的軟體界面的部分,來創建一些自定義部分的內容。

根據其中顯示的內容部分,製作了一個用戶控制項,在其中添加一個LayoutControl方便控制佈局,添加一些標簽以及設置了一些圖標,得到下圖所示。

其中定義的用戶控制項的源碼部分,繼承自XtraUserControl用戶控制項基類(如果是傳統樣式的Winform界面,可以繼承自UserControl),修改其中源碼增加對應的屬性,方便動態設置用戶控制項的相關屬性,如顏色塊,項目背景色,以及綁定的對象信息等內容。

然後通過自定義控制項的事件或者方法對界面內容進行更新處理即可。完成後我們看界面的效果如下所示,較為符合實際的效果即可。

一般來說,一個窗體用戶控制項不多的情況下,Winform界面的效果還是挺好的,如果界面的用戶控制項很多,如超過幾千個,那麼可能會有性能問題,之前在隨筆《使用Winform開發自定義用戶控制項,以及實現相關自定義事件的處理》中介紹的關於動態展現大量歷史號碼信息的自定義控制項的時候,就會出現一些句柄創建錯誤的問題。

控制項集合可以通過佈局TableLayoutPanel(表格佈局)或者FlowLayoutPanel(順序流佈局)來添加即可。如果利用利用TableLayoutPanel來展示,那麼需要設置好每列的寬度或者比例,如下界面所示。

表格的行列定義如下所示。

由於自定義控制項,我們需要跟蹤用戶的單擊處理,並且需要把這個邏輯逐步推動到頂級界面上去進行處理,因此需要定義一個事件信息,如下所示。

        /// <summary>
        /// 事件處理
        /// </summary>
        public EventHandler<ClickEventData> ClickEventHandler { get; set; }

控制項的動態添加處理,可以同時指定它的匿名事件的處理邏輯,從而對控制項的事件進行更新。

    var controlList = new List<LotteryItemControl2>();
    foreach (var info in list)
    {
        var control = new LotteryItemControl2();

        control.Qi = info.LineNo.ToString("D2");
        var numberList = new List<string>()
        {
            info.No1.ToString("D2"),
            info.No2.ToString("D2"),
            info.No3.ToString("D2"),
            info.No4.ToString("D2"),
            info.No5.ToString("D2"),
            info.No6.ToString("D2"),
            info.No7.ToString("D2"),
        };
        control.NumberList = numberList;
        control.BindData();

        control.ClickEventHandler += (s, data) =>
        {
            //遍歷所有的控制項統一處理樣式
            foreach (var subCtrl in panel.Controls)
            {
                if (subCtrl is LotteryItemControl2 lottery)
                {
                    lottery.SetSelected(data);
                }
            }
        };
        controlList.Add(control);
    }
    this.panel.Controls.AddRange(controlList.ToArray());

如果我們不喜歡每個控制項都對事件進行一個層層的處理,我們也可以引入MediatR來實現事件匯流排的處理,如我隨筆介紹《在Winform系統開發中,使用MediatR來實現類似事件匯流排的消息處理》,

MediatR的GitHub項目地址:https://github.com/jbogard/MediatR

我們在程式啟動的時候,註入對應的介面服務IMediator,那麼我們就可以通過該靜態類的 GetService<T>() 方法獲取對應的註入介面IMediator,我們需要利用該介面來發送Send請求/應答命令或者發佈Publish消息的處理。

public partial class TestMediatR : BaseForm
{
    private readonly IMediator _mediator;

    public TestMediatR()
    {
        InitializeComponent();

        _mediator = ServiceLocator.GetService<IMediator>();
    }

MediatR是一個跨平臺通過一種進程內消息傳遞機制,進行請求/響應、命令、查詢、通知和事件的消息傳遞,並通過C#泛型來支持消息的智能調度,其目的是消息發送和消息處理的解耦。它支持以單播和多播形式使用同步或非同步的模式來發佈消息,創建和偵聽事件。它主要的幾個對象:

  IMediator:主要提供Send與Publish方法,需要執行的命令都是通過這兩個方法實現

  IRequest、IRequest<T>命令查詢 | 處理類所繼承的介面,一個有返回類型,一個無返回類型,一個查詢對應一個處理類,程式集只認第一個掃描到的類。

  IRequestHandler<in TRequest,TResponse>(實現Handle方法) :命令處理介面。命令查詢 | 處理類繼承它,也可以繼承AsyncRequestHandler(實現抽象Handle方法)、RequestHandler(實現抽象Handle方法)介面

  INotification命令查詢 | 處理類所繼承的介面這個沒有返回,與IRequest不通的是可以對於多個處理類。

  INotificationHandler<in TNotification>:與IRequestHandler一樣的只不過這是INotification的處理介面。

例如我們發送消息後,收到應答消息結果,展示在界面中的如下所示。

/// <summary>
/// 使用請求、應答的消息進行測試,獲得返回結果後輸出顯示
/// </summary>
private async void btnSend_Click(object sender, EventArgs e)
{
    //應答處理
    var outputMessage = await _mediator.Send(new RetrieveInfoCommandRequest
    {
        Text = this.txtSend.Text
    });
    Console.WriteLine(outputMessage.OutputMessage);
    this.txtReceived.AppendText(outputMessage.OutputMessage + Environment.NewLine);
}

 

如果控制項比較多,處理的時候,刷新的時候記得移除面板上已經添加的控制項。

//清空界面
while (panel.Controls.Count > 0)
{
    var controltoremove = panel.Controls[0];
    panel.Controls.RemoveAt(0);
    controltoremove.Dispose();
}
panel.Controls.Clear();

 

2、《SqlSugar開發框架》Winform界面中的自定義的用戶控制項的一些處理

例如我們在附件管理的時候,對於一些窗體的信息,我們需要瞭解該業務對應的附件信息有幾個,並且提供入口可以查看或者管理附件列表,那麼我們可以根據需要封裝一個自定義的附件管理的自定義用戶控制項。

 在實際界面應用的時候,由於附件管理的自定義控制項已經封裝好了,所以在使用的時候,拖動到界面即可,如下界面所示。

我們在做病歷管理的時候,就需要大量用到不同的分類的附件信息的展示,如下界面效果所示。

還有就是有時候,對於許可權管理裡面,部門信息在不少的地方用到,如果每次對原始的下拉列表處理,那麼增加不少工作量,如果把它封裝為自定義控制項,和常規的控制項一樣使用即可,就會很方便,如下界面所示。

 它的實際展示效果如下所示。

單擊下拉列表後,展示部門的列表信息。

同理,用戶控制項一旦創建後,我們可以在很多需要的地方直接使用,省卻初始化的一些代碼操作。

 我們在初始化的時候,顯示相關的部門列表,選擇後獲得部門的ID,也可以設置部門的ID。

/// <summary>
/// 部門顯示控制項
/// </summary>
public partial class DeptControl : XtraUserControl
{
    public string ParentOuID = "-1";

    /// <summary>
    /// 選擇的值發生變化的時候
    /// </summary>
    public event EventHandler EditValueChanged;

    public DeptControl()
    {
        InitializeComponent();
        this.txtDept.EditValueChanged += new EventHandler(cmbUpperOU_EditValueChanged);
    }

    void cmbUpperOU_EditValueChanged(object sender, EventArgs e)
    {
        if (EditValueChanged != null)
        {
            EditValueChanged(sender, e);
        }
    }

    private async void DeptControl_Load(object sender, EventArgs e)
    {
        if (!this.DesignMode)
        {
            //限定用戶的選擇級別
            var list = await Portal.gc.GetMyTopGroup();
            foreach (OuInfo OuInfo in list)
            {
                if (OuInfo != null)
                {
                    this.ParentOuID = OuInfo.Id.ToString();
                }
            }

            Init();
        }
    }

需要可以響應相關的編輯事件,用來觸發關聯的信息變化,如下所示是自定義控制項的使用代碼。

public partial class FrmEditUser : BaseEditForm
{

    public FrmEditUser()
    {
        InitializeComponent();

        this.txtDept.EditValueChanged += new EventHandler(txtDept_EditValueChanged);
    }

    void txtDept_EditValueChanged(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(txtDept.Value))
        {
            InitManagers(txtDept.Value.ToInt32());
        }
    }

在介紹一個場景,我們在一些選擇用戶的界面中,如CRM中對於分配用戶、工作流中選擇流程用戶的操作中,往往需要選擇系統的人員列表,可以多個選擇,那麼我們可以設計界面如下所示。

 其中選擇的人員用紅色方框標識,這個部分的用戶和移除圖標是自定義控制項,界面如下所示。

主要就是方便對用戶進行顯示和移除設置的一些簡單的封裝。

在比如在工作流的創建入口中,我們展示相關可以創建流程的快速入口,通過一些圖片、文字來展示工作流程的信息,單擊事件進行彈出不同的流程對話框處理過程。

這個過程主要就是美觀性的要求,是相對於全部文本信息的單調有一些改善的效果。

 

鏈接附註

如對我們的代碼生成工具有興趣,可以到官網下載使用《代碼生成工具Database2Sharp》。

如需瞭解我們官網對《SqlSugar開發框架》的介紹,可以參考《SqlSugar開發框架》瞭解。

如需閱讀我們對於《SqlSugar開發框架》文章介紹,可以參考博客園的隨筆標簽《SqlSugar隨筆 , WPF隨筆》學習瞭解。

 

專註於代碼生成工具、.Net/.NetCore 框架架構及軟體開發,以及各種Vue.js的前端技術應用。著有Winform開發框架/混合式開發框架、微信開發框架、Bootstrap開發框架、ABP開發框架、SqlSugar開發框架等框架產品。
  轉載請註明出處:撰寫人:伍華聰  http://www.iqidi.com 
    

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

-Advertisement-
Play Games
更多相關文章
  • 前言: 在本篇 Taurus.MVC WebMVC 入門開發教程的第四篇文章中, 我們將學習如何實現數據列表的綁定,通過使用 List<Model> 來展示多個數據項。 我們將繼續使用 Taurus.Mvc 命名空間,同時探討如何在視圖中綁定並顯示一個 Model 列表。 步驟1:創建 Model ...
  • 問題背景 有同事聯繫我說,在生產環境上,訪問不了我負責的common服務,然後我去檢查common服務的health endpoint, 沒問題,然後我問了下異常,timeout導致的System.OperationCanceledException。那大概率是客戶端的問題,會不會是埠耗盡,用ne ...
  • 概述:.NET提供多種定時器,如System.Windows.Forms.Timer適用於UI,System.Web.UI.Timer用於Web,System.Diagnostics.Timer用於性能監控,System.Threading.Timer和System.Timers.Timer用於一般 ...
  • 概述:Cron表達式是一種強大的定時任務調度工具,通過配置不同欄位實現靈活的時間規定。在.NET中,Quartz庫提供了簡便的方式配置Cron表達式,實現精準的定時任務調度。這種靈活性和可擴展性使得開發者能夠根據需求輕鬆地制定和管理定時任務,例如每天備份系統日誌或其他重要操作。 Cron表達式詳解 ...
  • 概述:本文介紹了在C#程式開發中如何利用自定義擴展方法測量代碼執行時間。通過使用簡單的Action委托,開發者可以輕鬆獲取代碼塊的執行時間,幫助優化性能、驗證演算法效率以及監控系統性能。這種通用方法提供了一種便捷而有效的方式,有助於提高開發效率和代碼質量。 在軟體開發中,瞭解代碼執行時間是優化程式性能 ...
  • 概述:在WPF中,通過EventHandler可實現基礎和高級的UI更新方式。基礎用法涉及在類中定義事件,併在UI中訂閱以執行更新操作。高級用法藉助Dispatcher類,確保在非UI線程上執行操作後,通過UI線程更新界面。這兩種方法提供了靈活而可靠的UI更新機制。 在WPF(Windows Pre ...
  • 是在MVVM中用來傳遞消息的一種方式。它是在MVVMLight框架中提供的一個實現了IMessenger介面的類,可以用來在ViewModel之間、ViewModel和View之間傳遞消息。 Send 接受一個泛型參數,表示要發送的消息內容。 Register 方法用於註冊某個對象接收消息。 pub ...
  • 在本篇教程中,我們學習瞭如何在 Taurus.MVC WebMVC 中進行數據綁定操作。我們還學習瞭如何使用 ${屬性名稱} CMS 語法來綁定頁面上的元素與 Model 中的屬性。通過這些步驟,我們成功實現了一個簡單的數據綁定示例。 ...
一周排行
    -Advertisement-
    Play Games
  • 隨著Aspire發佈preview5的發佈,Microsoft.Extensions.ServiceDiscovery隨之更新, 服務註冊發現這個屬於老掉牙的話題解決什麼問題就不贅述了,這裡主要講講Microsoft.Extensions.ServiceDiscovery(preview5)以及如何 ...
  • 概述:通過使用`SemaphoreSlim`,可以簡單而有效地限制非同步HTTP請求的併發量,確保在任何給定時間內不超過20個網頁同時下載。`ParallelOptions`不適用於非同步操作,但可考慮使用`Parallel.ForEach`,儘管在非同步場景中謹慎使用。 對於併發非同步 I/O 操作的數量 ...
  • 1.Linux上安裝Docken 伺服器系統版本以及內核版本:cat /etc/redhat-release 查看伺服器內核版本:uname -r 安裝依賴包:yum install -y yum-utils device-mapper-persistent-data lvm2 設置阿裡雲鏡像源:y ...
  • 概述:WPF界面綁定和渲染大量數據可能導致性能問題。通過啟用UI虛擬化、非同步載入和數據分頁,可以有效提高界面響應性能。以下是簡單示例演示這些優化方法。 在WPF中,當你嘗試綁定和渲染大量的數據項時,性能問題可能出現。以下是一些可能導致性能慢的原因以及優化方法: UI 虛擬化: WPF提供了虛擬化技術 ...
  • 引言 上一章節介紹了 TDD 的三大法則,今天我們講一下在單元測試中模擬對象的使用。 Fake Fake - Fake 是一個通用術語,可用於描述 stub或 mock 對象。 它是 stub 還是 mock 取決於使用它的上下文。 也就是說,Fake 可以是 stub 或 mock Mock - ...
  • 為.net6在CentOS7上面做準備,先在vmware虛擬機安裝CentOS 7.9 新建CentOS764位的系統 因為CentOS8不更新了,所以安裝7;簡單就一筆帶過了 選擇下載好的操作系統的iso文件,下載地址https://mirrors.aliyun.com/centos/7.9.20 ...
  • 經過前面幾篇的學習,我們瞭解到指令的大概分類,如:參數載入指令,該載入指令以 Ld 開頭,將參數載入到棧中,以便於後續執行操作命令。參數存儲指令,其指令以 St 開頭,將棧中的數據,存儲到指定的變數中,以方便後續使用。創建實例指令,其指令以 New 開頭,用於在運行時動態生成並初始化對象。方法調用指... ...
  • LiteDB 是一個輕量級的嵌入式 NoSQL 資料庫,其設計理念與 MongoDB 類似,但它是完全使用 C# 開發的,因此與 C# 應用程式的集成非常順暢。與 SQLite 相比,LiteDB 提供了 NoSQL(即鍵值對)的數據存儲方式,並且是一個開源且免費的項目。它適用於桌面、移動以及 We ...
  • 1 開源解析和拆分文檔 第三方的工具去對文件解析拆分,去將我們的文件內容給提取出來,並將我們的文檔內容去拆分成一個小的chunk。常見的PDF word mark down, JSON、HTML。都可以有很好的一些模塊去把這些文件去進行一個東西去提取。 優勢 支持豐富的文檔類型 每種文檔多樣化選擇 ...
  • OOM是什麼?英文全稱為 OutOfMemoryError(記憶體溢出錯誤)。當程式發生OOM時,如何去定位導致異常的代碼還是挺麻煩的。 要檢查OOM發生的原因,首先需要瞭解各種OOM情況下會報的異常信息。這樣能縮小排查範圍,再結合異常堆棧、heapDump文件、JVM分析工具和業務代碼來判斷具體是哪 ...