轉(zhuǎn)帖|使用教程|編輯:龔雪|2024-03-29 10:27:34.863|閱讀 99 次
概述:本文主要介紹使用Winform開(kāi)發(fā)自定義用戶(hù)控件以及實(shí)現(xiàn)相關(guān)自定義事件的處理,歡迎下載最新版工具體驗(yàn)!
# 界面/圖表報(bào)表/文檔/IDE等千款熱門(mén)軟控件火熱銷(xiāo)售中 >>
相關(guān)鏈接:
在我們一些非標(biāo)的用戶(hù)界面中,往往需要自定義用戶(hù)控件界面,從而實(shí)現(xiàn)不同的內(nèi)容展示和處理規(guī)則,本文介紹使用Winform開(kāi)發(fā)自定義用戶(hù)控件,以及實(shí)現(xiàn)相關(guān)自定義事件的處理。
PS:給大家推薦一個(gè)C#開(kāi)發(fā)可以用到的界面組件——DevExpress WinForms,它能完美構(gòu)建流暢、美觀(guān)且易于使用的應(yīng)用程序,無(wú)論是Office風(fēng)格的界面,還是分析處理大批量的業(yè)務(wù)數(shù)據(jù),它都能輕松勝任!
DevExpress技術(shù)交流群9:909157416 歡迎一起進(jìn)群討論
對(duì)于比較規(guī)范的界面,需要進(jìn)行一定的分析,以便從中找到對(duì)應(yīng)的規(guī)則,逐步細(xì)化為自定義用戶(hù)控件的方式,例如對(duì)于由下面多個(gè)集合組成的界面內(nèi)容。
我們截取其中之一,也就是由這些內(nèi)容多個(gè)組合而成,集合可以通過(guò)布局TableLayoutPanel(表格布局)或者FlowLayoutPanel(順序流布局)來(lái)添加即可。
而其中之一的內(nèi)容,不同的顏色方格又可以定義為一個(gè)用戶(hù)控件,因此最終有多個(gè)小方格組成的用戶(hù)控件的。
而單個(gè)用戶(hù)控件,可能承載不同的內(nèi)容,我們可以定義更多的接口屬性以及一些事件來(lái)處理相關(guān)的邏輯。
甚至還可以在一個(gè)單元格里面放置更多的內(nèi)容,如放置一些特殊的標(biāo)簽來(lái)展示信息。
為了使用戶(hù)控件更加規(guī)范化,我們可以定義一個(gè)接口,聲明相關(guān)的屬性和處理方法,如下代碼所示。
/// <summary> /// 自定義控件的接口 /// </summary> public interface INumber { /// <summary> /// 數(shù)字 /// </summary> string Number { get; set; } /// <summary> /// 數(shù)值顏色 /// </summary> Color Color { get; set; } /// <summary> /// 顯示文本 /// </summary> string Animal { get; set; } /// <summary> /// 顯示文本 /// </summary> string WuHan { get; set; } /// <summary> /// 設(shè)置選中的內(nèi)容的處理 /// </summary> /// <param name="data">事件數(shù)據(jù)</param> void SetSelected(ClickEventData data); }
然后我們創(chuàng)建一個(gè)用戶(hù)控件,并命名為NumberItem,并使它繼承前面定義的接口 INumber ,實(shí)現(xiàn)相關(guān)的屬性和事件,如下代碼所示。
/// <summary> /// 自定義用戶(hù)控件 /// </summary> public partial class NumberItem : UserControl, INumber { /// <summary> /// 數(shù)字 /// </summary> public string Number { get; set; } /// <summary> /// 顏色 /// </summary> public Color Color { get; set; } /// <summary> /// 顯示文本 /// </summary> public string Animal { get; set; } /// <summary> /// 顯示文本 /// </summary> public string WuHan { get; set; }
其中處理方法SetSelected先保留為空,后面繼續(xù)完善。
/// <summary> /// 設(shè)置選中的數(shù)值 /// </summary> /// <param name="data">傳遞的數(shù)據(jù)</param> public void SetSelected(ClickEventData data) { }
由于自定義控件,我們需要跟蹤用戶(hù)的單擊處理,并且需要把這個(gè)邏輯逐步推動(dòng)到頂級(jí)界面上去進(jìn)行處理,因此需要定義一個(gè)事件信息,如下所示。
/// <summary> /// 事件處理 /// </summary> public EventHandler<ClickEventData> ClickEventHandler { get; set; }
其中ClickEventData是我們定義的一個(gè)數(shù)據(jù),用來(lái)承載用戶(hù)單擊的類(lèi)型和值內(nèi)容的信息結(jié)構(gòu),如下代碼所示。
/// <summary> /// 對(duì)自定義控件觸發(fā)的事件信息 /// </summary> public class ClickEventData { /// <summary> /// 事件觸發(fā)類(lèi)型 /// </summary> public ClickEventType ClickEventType { get; set; } = ClickEventType.Number; /// <summary> /// 傳遞值 /// </summary> public string Value { get; set; } public ClickEventData() { } /// <summary> /// 參數(shù)化構(gòu)造 /// </summary> /// <param name="clickEventType">事件觸發(fā)類(lèi)型</param> /// <param name="value">傳遞值</param> public ClickEventData(ClickEventType clickEventType, string value) { ClickEventType = clickEventType; Value = value; } }
再創(chuàng)建一個(gè)整合多個(gè)號(hào)碼數(shù)值的一個(gè)自定義控件,它也是一個(gè)完整的單元之一,我們命名為 LotteryItemControl2。
我們相當(dāng)于把前面的自定義控件,組合為一個(gè)新的用戶(hù)控件,形成一個(gè)相對(duì)完整的部分,這里提供兩種思路,一種是使用常規(guī)的用戶(hù)控件,拖動(dòng)已有的用戶(hù)控件組合而成,如下所示。
另一種是利用TableLayoutPanel,動(dòng)態(tài)添加控件進(jìn)行組合,可以根據(jù)預(yù)設(shè)的TableLayout布局實(shí)現(xiàn)控件的順序添加。
表格的行列定義如下所示:
兩種方式都可以實(shí)現(xiàn)類(lèi)似的效果,我們這里以第一種為例實(shí)現(xiàn)。
public partial class LotteryItemControl2 : UserControl { /// <summary> /// 事件處理 /// </summary> public EventHandler<ClickEventData> ClickEventHandler { get; set; } /// <summary> /// 第幾期 /// </summary> public string Qi { get; set; } /// <summary> /// 數(shù)據(jù)列表 /// </summary> public List<string> NumberList { get; set; }
數(shù)據(jù)列表就是展示在自定義控件的數(shù)字。在控件中定義一個(gè)函數(shù) 統(tǒng)一處理數(shù)據(jù)內(nèi)容的綁定顯示。
/// <summary> /// 綁定數(shù)據(jù) /// </summary> public void BindData() { //控件列表,方便統(tǒng)一處理 var controlList = new List<NumberItem> { this.numberItem1, this.numberItem2, this.numberItem3, this.numberItem4, this.numberItem5, this.numberItem6, this.numberItem7 }; this.labelQi.Text = Qi; //設(shè)置第幾期 for(int i =0; i < this.NumberList.Count; i++) { var control = controlList[i]; var number = this.NumberList[i]; var shenxiao = LotteryToolHelper.NumberToShenXiaoDict[number]; //"馬"; var wuhan = LotteryToolHelper.NumberToWuhanDict[number];//"土" control.Number = number; control.Animal = shenxiao; control.WuHan = wuhan; var colorStr = LotteryToolHelper.ColorBall[number]; control.Color = LotteryToolHelper.GetColor(colorStr); //item % 2 == 0 ? Color.Red : Color.Green; control.BindData(); control.ClickEventHandler += (s, data) => { if (ClickEventHandler != null) { //傳遞父控件統(tǒng)一處理 ClickEventHandler(s, data); } }; } }
其中該控件也可以設(shè)置選中,有具體的子控件調(diào)用設(shè)置選中的處理規(guī)則即可。
/// <summary> /// 遍歷控件,設(shè)置選中的數(shù)值 /// </summary> /// <param name="data">傳遞信息</param> public void SetSelected(ClickEventData data) { foreach (var control in this.Controls) { if (control is NumberItem item) { item.SetSelected(data); } } }
為了提高性能,我們一般往往需要設(shè)置窗體或者Panel為雙緩沖DoubleBuffered = true。
在主界面的面板中,我們可以添加一個(gè)FlowLayoutPanel 來(lái)按順序堆疊用戶(hù)控件,具體的實(shí)現(xiàn)邏輯就是根據(jù)從數(shù)據(jù)庫(kù)獲得的記錄進(jìn)行展示即可。
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) => { //遍歷所有的控件統(tǒng)一處理樣式 foreach (var subCtrl in panel.Controls) { if (subCtrl is LotteryItemControl2 lottery) { lottery.SetSelected(data); } } }; controlList.Add(control); } this.panel.Controls.AddRange(controlList.ToArray());
以上就是相關(guān)的處理邏輯,用來(lái)組織自定義用戶(hù)控件的統(tǒng)一展示處理。
如果需要用戶(hù)進(jìn)行不同條件的數(shù)據(jù)展示,那么展示前,就需要重新清空面板中的控件,如下所示。
//清空界面 while (panel.Controls.Count > 0) { var controltoremove = panel.Controls[0]; panel.Controls.RemoveAt(0); controltoremove.Dispose(); } panel.Controls.Clear();
上面代碼記得調(diào)用Dispose方法來(lái)釋放控件資源。
在最小的自定義控件中,我們可能需要根據(jù)一些條件進(jìn)行一些自定義繪制處理,以突出顯示不同的內(nèi)容(重點(diǎn)強(qiáng)調(diào)選中項(xiàng)目)。
private void NumberItem_Paint(object sender, PaintEventArgs e)
如下是一些特殊的繪制處理內(nèi)容。
private void NumberItem_Paint(object sender, PaintEventArgs e) { this.BackColor = (this.BorderStyle == BorderStyle.FixedSingle) ? Color.Yellow : Color.Transparent; if (this.BorderStyle == BorderStyle.FixedSingle) { IntPtr hDC = GetWindowDC(this.Handle); Graphics g = Graphics.FromHdc(hDC); ControlPaint.DrawBorder( g, new Rectangle(0, 0, this.Width, this.Height), _borderColor, _borderWidth, ButtonBorderStyle.Solid, _borderColor, _borderWidth, ButtonBorderStyle.Solid, _borderColor, _borderWidth, ButtonBorderStyle.Solid, _borderColor, _borderWidth, ButtonBorderStyle.Solid); g.Dispose(); ReleaseDC(Handle, hDC); } }
最終展示效果如下所示,黃色強(qiáng)調(diào)的處理,是選中相同號(hào)碼的處理事件結(jié)果繪制。
本文轉(zhuǎn)載自:
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自: