原創|其它|編輯:郝浩|2009-07-08 09:57:16.000|閱讀 735 次
概述:園子里的大蝦們總是討論System.Web的控件,大多數以Web的用戶自定義控件為主,卻很少有人寫些關于Windows.Forms的用戶控件或者自定義控件,原因大概是都開發web的,相比之下Windows.Forms的自定義控件的界面難繪制。誒,想起去年為了實現一個Winform程序,自己琢磨用戶控件在院子里連點資料都找不到。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
園子里的大蝦們總是討論System.Web的控件,大多數以Web的用戶自定義控件為主,卻很少有人寫些關于Windows.Forms的用戶控件或者自定義控件,原因大概是都開發web的,相比之下Windows.Forms的自定義控件的界面難繪制。誒,想起去年為了實現一個Winform程序,自己琢磨用戶控件在院子里連點資料都找不到。
首先聲明,我封裝的是Windows.Forms的用戶控件,不是自定義控件。至于為什么寫用戶控件而不是自定義控件,我相信大家都知道用戶控件只要繼承UserControl即可,拖拽幾個Win自帶的控件進來寫幾句即可。我寫用戶控件的目的是為了提高開發效率,同時為了美觀統一,所以界面效果自然是沒有控件商的產品漂亮。
當然,最后是有源代碼下載,先上幾張圖圖。
圖1 標題文本框
圖2 彈出窗口
圖3 分頁表格
圖4 下拉樹
怎么開發用戶控件很簡單,不做介紹,寫這篇文章是想向大家介紹一下思想。
通常我們寫應用程序的時候,都會出現那種信息錄入界面,就像是“標題然后后面緊接著加一個文本框”(見圖1),像大眾設計的話,肯定是拖拽兩個控件進來,一個是Label,一個是TextBox,然后布局一下。其實很多時候我們只用到了簡單的一個文本框內容的讀取以及一個文本標題的顯示,所以很多情況下我們就可以把這兩個合并成一個帶標題的文本框用戶控件,這樣就能節省更多的開發時間了。當然還有其他更多的好處就不在這里作過多介紹,讀者請看代碼自去體會。
以上只是一個非常簡單的場合,介紹一個比較復雜點的場合吧。寫應用程序的同志們肯定會遇到那種需要彈出窗口進行選擇某條記錄然后返回到主窗口來進行繼續操作的時候(見圖2),若像普通設計的話,我們每個這種場合都需要設計同樣的工作,所以為了節省工作量,我把這個封裝了,為了能讓彈出窗口和主窗口進行通訊,我定義了接口并且定義了參數。當然這樣是有點局限性,但是能解決很大部分情況。可能大家會問,不會那么簡單吧,實際上是不簡單,但是只要按照約定進行開發就容易了。
被彈出窗口需要繼承的接口(用來觸發選擇動作以及傳遞參數使用,PS:實際改成委托更好點,好像其他控件有這么做)
public interface ISelectButtons
{
DialogValue MyDialogValue { get; set; }
void SetSelect();
}
彈出主窗口需要將控件MyTextBoxButtonSelect拖拽進來,并設置相關參數,注意一下重要參數:
string DialogAssemblyName,被彈出窗口的命名空間。(為反射作準備)
string DialogAddForm,若新建,被彈出的窗口類名。(為了統一彈出窗口的界面風格,故定義了MyForm用戶控件,其他所有與內容相關的都定義成了功能性用戶控件)
string DialogAddUserControl,若新建,被彈出的用戶控件類名。
同樣還有選擇的彈出窗口,叫做DialogSelectForm和DialogSelectUserControl。
在這里把控件的部分源代碼貼出,下面是點擊新建按鈕的動作:
private void buttonAdd_Click(object sender, EventArgs e)
{
base.OnClick(e);
try
{
if (String.IsNullOrEmpty(DialogAddForm) && String.IsNullOrEmpty(DialogAddUserControl))
return;
Form f = GetForm(DialogAddForm);
UserControl u = GetUserControl(DialogAddUserControl);
MyDialogValue = new DialogValue();
((ISelectButtons)u).MyDialogValue = MyDialogValue;
((ISelectButtons)u).MyDialogValue.FromValue = GetMyTextBox();
((ISelectButtons)u).MyDialogValue.ReturnValue = MyValue;
f.AutoSize = true;
f.Controls.Add(u);
if (u.Tag != null)
f.Text = " " + u.Tag.ToString();
f.ShowDialog();
if (!String.IsNullOrEmpty(MyDialogValue.ReturnText) && !String.IsNullOrEmpty(MyDialogValue.ReturnValue))
SetSelectValue();
}
catch (Exception ex)
{
ex.Source += String.Format(" DialogAddUserControl:{0}", DialogAddUserControl);
ExceptionHelper.Exception(ex);
}
}
不要以為到了這里我的山寨版用戶控件就沒了,其實不然,還有很多很多東西,拿出來分享給大家,希望能讓大家看懂,看不懂的就不能理解我的一番苦心,誒,能理解我的人太少了,曾經很長一段時間號稱孤狼,最近才把真名換出來。好了不多說了,這里介紹一下大家常用的DataGridView列表展示情景(見圖3),我封裝了一個即能分頁又能導出Excel的控件,而且里面的功能跟業務毫無關系,當然要用它也要按照約定來進行開發,即它的容器(窗口)需要實現接口IPagination。
接口代碼很簡單:
public interface IPagination
{
void BindData();
//void SelectRow(); //(PS:此處為什么注釋,不記得了。反正去年寫的時候是想實現行選擇動作來觸發什么事件的,今年沒事才拿出來給大家分享。)
}
MyDataGridView有幾個參數需要重視:
int PageSize
int CurrentPageIndex
int RowsTotalCount
Object DataSource
貼出一下MyDataGridView用戶控件的部分代碼:
public int GetPageCount()
{
if ((RowsTotalCount == 0) || (PageSize == 0))
return 0;
int i = RowsTotalCount / PageSize;
if (RowsTotalCount % PageSize > 0)
i++;
return i;
}
private IPagination FindControlIPagination()
{
Control c = this.Parent;
while (c != null)
{
if (c is IPagination)
break;
c = c.Parent;
}
if (!(c is IPagination))
throw new Exception("No IPagination Control in this UserControl or Form.");
return c as IPagination;
}
public void DataBind()
{
dataGridViewDefault.DataSource = DataSource;
toolStripLabelRowsTotalCount.Text = String.Format("共計:{0}條 {1}條/頁", RowsTotalCount, PageSize);
toolStripLabelCurrentPage.Text = String.Format("{0}/{1}", CurrentPageIndex, GetPageCount());
SetEnabled();
}
private void ReDataBind()
{
IPagination page = FindControlIPagination();
page.BindData();
}
恩恩,寫到這里本打算就此收筆了,但是突然看到了一個曾經折騰了好久才搞出來的一個控件DropDownTreeView,這個控件是實現了下拉樹選擇功能(見圖4),與其他用戶控件比,比較特殊點就是他不是繼承自UserControl,而是來自于ComboBox,然而其實ComboBox是間接繼承自Control,所以DropDownTreeView可以定義自己的TreeView控件來進行展示與承載數據,唯一需要處理的就是找到Windows句柄獲取點擊ComboBox的動作來進行展收樹,看部分代碼:
private void ShowDropDown()
{
if (dropDown != null)
{
treeViewHost.Size = new Size(DropDownWidth - 2, DropDownHeight);
dropDown.Show(this, 0, this.Height);
}
}
protected override void WndProc(ref Message m)
{
try
{
if (m.Msg == WM_LBUTTONDBLCLK || m.Msg == WM_LBUTTONDOWN)
{
ShowDropDown();
return;
}
base.WndProc(ref m);
}
catch (Exception ex)
{
CHF.Windows.Command.ExceptionHelper.Exception(ex);
}
}
算了,算了,再看就寫不完了,貼出一下我的類庫里有多少個用戶控件,很多都是見了名字就能知道什么意思的。
最后貼出原代碼:
至于調用的Demo,我就不便把我整個項目代碼都給出來,畢竟它已經在市面上還活著呢//soft.bxren.cn
(給了幾個調用的Demo文件,但是會報錯,因為我沒有給出完整的Demo部分,我相信大蝦們能通過源碼看出效果來)
由于是早期做程序用的,也沒有特意去進行重構和包裝,但是很實用。這次拿出來也是臨時應付,也沒有作很好的介紹和修剪代碼,不會用就問,本人臉皮厚,好不好用我也不害臊,反正磚頭砸我頭不會疼~ 不信試試。。。。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:博客園