轉(zhuǎn)帖|使用教程|編輯:龔雪|2024-03-29 10:27:34.863|閱讀 113 次
概述:本文主要介紹使用Winform開發(fā)自定義用戶控件以及實現(xiàn)相關(guān)自定義事件的處理,歡迎下載最新版工具體驗!
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
在我們一些非標(biāo)的用戶界面中,往往需要自定義用戶控件界面,從而實現(xiàn)不同的內(nèi)容展示和處理規(guī)則,本文介紹使用Winform開發(fā)自定義用戶控件,以及實現(xiàn)相關(guān)自定義事件的處理。
PS:給大家推薦一個C#開發(fā)可以用到的界面組件——DevExpress WinForms,它能完美構(gòu)建流暢、美觀且易于使用的應(yīng)用程序,無論是Office風(fēng)格的界面,還是分析處理大批量的業(yè)務(wù)數(shù)據(jù),它都能輕松勝任!
DevExpress技術(shù)交流群9:909157416 歡迎一起進群討論
對于比較規(guī)范的界面,需要進行一定的分析,以便從中找到對應(yīng)的規(guī)則,逐步細(xì)化為自定義用戶控件的方式,例如對于由下面多個集合組成的界面內(nèi)容。
我們截取其中之一,也就是由這些內(nèi)容多個組合而成,集合可以通過布局TableLayoutPanel(表格布局)或者FlowLayoutPanel(順序流布局)來添加即可。
而其中之一的內(nèi)容,不同的顏色方格又可以定義為一個用戶控件,因此最終有多個小方格組成的用戶控件的。
而單個用戶控件,可能承載不同的內(nèi)容,我們可以定義更多的接口屬性以及一些事件來處理相關(guān)的邏輯。
甚至還可以在一個單元格里面放置更多的內(nèi)容,如放置一些特殊的標(biāo)簽來展示信息。
為了使用戶控件更加規(guī)范化,我們可以定義一個接口,聲明相關(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)建一個用戶控件,并命名為NumberItem,并使它繼承前面定義的接口 INumber ,實現(xiàn)相關(guān)的屬性和事件,如下代碼所示。
/// <summary>
/// 自定義用戶控件
/// </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)
{
}
由于自定義控件,我們需要跟蹤用戶的單擊處理,并且需要把這個邏輯逐步推動到頂級界面上去進行處理,因此需要定義一個事件信息,如下所示。
/// <summary>
/// 事件處理
/// </summary>
public EventHandler<ClickEventData> ClickEventHandler { get; set; }
其中ClickEventData是我們定義的一個數(shù)據(jù),用來承載用戶單擊的類型和值內(nèi)容的信息結(jié)構(gòu),如下代碼所示。
/// <summary>
/// 對自定義控件觸發(fā)的事件信息
/// </summary>
public class ClickEventData
{
/// <summary>
/// 事件觸發(fā)類型
/// </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ā)類型</param>
/// <param name="value">傳遞值</param>
public ClickEventData(ClickEventType clickEventType, string value)
{
ClickEventType = clickEventType;
Value = value;
}
}
再創(chuàng)建一個整合多個號碼數(shù)值的一個自定義控件,它也是一個完整的單元之一,我們命名為 LotteryItemControl2。
我們相當(dāng)于把前面的自定義控件,組合為一個新的用戶控件,形成一個相對完整的部分,這里提供兩種思路,一種是使用常規(guī)的用戶控件,拖動已有的用戶控件組合而成,如下所示。
另一種是利用TableLayoutPanel,動態(tài)添加控件進行組合,可以根據(jù)預(yù)設(shè)的TableLayout布局實現(xiàn)控件的順序添加。
表格的行列定義如下所示:
兩種方式都可以實現(xiàn)類似的效果,我們這里以第一種為例實現(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ù)字。在控件中定義一個函數(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。
在主界面的面板中,我們可以添加一個FlowLayoutPanel 來按順序堆疊用戶控件,具體的實現(xiàn)邏輯就是根據(jù)從數(shù)據(jù)庫獲得的記錄進行展示即可。
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)的處理邏輯,用來組織自定義用戶控件的統(tǒng)一展示處理。
如果需要用戶進行不同條件的數(shù)據(jù)展示,那么展示前,就需要重新清空面板中的控件,如下所示。
//清空界面
while (panel.Controls.Count > 0)
{
var controltoremove = panel.Controls[0];
panel.Controls.RemoveAt(0);
controltoremove.Dispose();
}
panel.Controls.Clear();
上面代碼記得調(diào)用Dispose方法來釋放控件資源。
在最小的自定義控件中,我們可能需要根據(jù)一些條件進行一些自定義繪制處理,以突出顯示不同的內(nèi)容(重點強調(diào)選中項目)。
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);
}
}
最終展示效果如下所示,黃色強調(diào)的處理,是選中相同號碼的處理事件結(jié)果繪制。
本文轉(zhuǎn)載自:
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@ke049m.cn
文章轉(zhuǎn)載自: