隨筆背景:在很多時候田篇,很多入門不久的朋友都會問我:我是從其他語言轉到C#開發(fā)的涉瘾,有沒有一些基礎性的資料給我們學習學習呢,你的框架感覺一下太大了商蕴,希望有個循序漸進的教程或者視頻來學習就好了瘾腰。
其實也許我們每天面對的太多東西了皆的,覺得很多都稀松平常了,即使很細微的地方蹋盆,可能我們都已經形成習慣了费薄。反過來,如果我們切換到其他領域栖雾,如IOS楞抡、android,那么開始我們可能對里面很多設計的規(guī)則不甚了解析藕,開始可能也是一頭霧水召廷。
本篇繼續(xù)上一篇《循序漸進開發(fā)WinForm項目(3)--Winform界面層的項目設計》,繼續(xù)介紹如何循序漸進開發(fā)Winform項目账胧,繼續(xù)介紹Winform界面模塊如何整合到主體項目工程里面竞慢,進行使用等操作,使得我們逐漸了解一個完整的開發(fā)方案過程治泥。
1筹煮、窗體界面的集成使用
上篇介紹了如何利用工具進行Winform界面層窗體的快速生成,并進行適當?shù)恼{整居夹,已達到合理布局败潦,顯示美觀等的效果,本篇繼續(xù)這一主題介紹下去准脂,上篇我們開發(fā)好的獨立界面模塊劫扒,如何在主體項目中集成使用呢?
首先我們把生成的界面層DLL復制到項目工程中狸膏,然后在主項目工程中添加相關的應用沟饥,如下所示。
然后湾戳,我們需要做的就是贤旷,在主體界面模塊里面添加一個功能按鈕的入口,如下所示是我在我的框架界面啟動模塊里面添加一個按鈕的效果院塞。
然后在按鈕的單擊事件里面遮晚,添加下面的代碼即可。
private void tool_Customer_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { ChildWinManagement.LoadMdiForm(this, typeof(WHC.TestProject.UI.FrmCustomer)); }
其中ChildWinManagement是公用類庫里面一個輔助類拦止,用來在多文檔的情況下進行窗體的展示县遣,傳入一個MDI的Parent的窗體對象引用糜颠,另外一個是構造顯示的窗體類型,它會根據(jù)類型來判斷是否已經實例化了萧求,如果存在就打開其兴,否則就創(chuàng)建一個新的窗體病顯示出來主界面里面。
啟動界面夸政,后看到的效果如下所示(我們在后臺添加一些測試數(shù)據(jù)后)元旬。
雙擊數(shù)據(jù)出來的編輯界面如下所示。
這樣守问,我們在還沒有添加任何代碼和邏輯實現(xiàn)的情況下匀归,基本的界面已經出來了,而且相關的數(shù)據(jù)存儲和顯示的功能已經存在耗帕,我們所需要做的就只是細化里面的內容即可穆端。
2、窗體界面的在插件化框架的集成使用
第一節(jié)中介紹的是傳統(tǒng)方式的界面模塊的繼承仿便,開發(fā)框架本身也還提供了另外一種方式的界面模塊集成方式体啰,插件化的模塊化集成。我們通過把相關的DLL復制到運行的目錄下嗽仪,并且在數(shù)據(jù)庫里面配置好相關的Winform模塊信息后荒勇,就可以在主界面中調用出來是用來。
關于插件化的框架實現(xiàn)的介紹闻坚,大家可以看看我前面寫的一篇博客文章《Winform開發(fā)框架之插件化應用框架實現(xiàn)》沽翔。
首先我們配置菜單的時候,登陸權限管理系統(tǒng)鲤氢,添加相關的菜單項目搀擂,如下所示西潘。當然卷玉,如果你有自己的菜單管理模塊,自己通過自己的手工設置好相關的信息即可喷市。
好相种,搞定菜單的動態(tài)配置后,我們重新登陸下系統(tǒng)的主界面品姓,看看有無變化了寝并。
從主界面的Ribbon工具欄,我們可以看到腹备,里面已經新增了一個客戶管理(紅色部分)的內容了衬潦,這個位置就是我們剛才新增菜單的位置。單擊菜單按鈕植酥,那么就會展現(xiàn)出來客戶管理的內容了镀岛。
整個主界面框架弦牡,加上打開的客戶管理界面,整體的效果是一個多文檔的界面效果漂羊。
3驾锰、集成登陸用戶信息
前面幾篇的隨筆,主要就是介紹給我們認識如何快速開發(fā)一個模塊走越,并且集成到系統(tǒng)框架里面進行使用椭豫,我們甚至還沒有開始編碼,就已經給我們處理好很多細節(jié)上的東西旨指,基本上就已經完成一個業(yè)務小模塊的展示工作了赏酥。
完成本文的前面兩個小節(jié),不知道你們有沒有發(fā)現(xiàn)谆构,我們好像還沒有真正的整合登陸的用戶信息呢今缚?在獨立的系統(tǒng)模塊開發(fā)過程中,我們如何整合登陸的用戶信息呢低淡?
我們重新回到開發(fā)的業(yè)務模塊的界面項目里面看看原來的編輯界面代碼姓言。
這里面對于保存新增的數(shù)據(jù),我們調整一下蔗蹋,把它的創(chuàng)建的人員和時間在代碼FrmEditCustomer.cs里面調整成合理的代碼何荚,記錄人員和當前時間。
/// <summary>
/// 編輯或者保存狀態(tài)下取值函數(shù)
/// </summary>
/// <param name="info"></param>
private void SetInfo(CustomerInfo info)
{
info.Name = txtName.Text;
info.Age = txtAge.Value.ToString().ToInt32();
}
/// <summary>
/// 新增狀態(tài)下的數(shù)據(jù)保存
/// </summary>
/// <returns></returns>
public override bool SaveAddNew()
{
CustomerInfo info = tempInfo;//必須使用存在的局部變量猪杭,因為部分信息可能被附件使用
SetInfo(info);
info.CreateTime = DateTime.Now;
info.Creator = LoginUserInfo.ID.ToString();//為了更好管理餐塘,我們這里存儲用戶的ID,而非名稱
try
{
#region 新增數(shù)據(jù)
bool succeed = BLLFactory<Customer>.Instance.Insert(info);
if (succeed)
{
//可添加其他關聯(lián)操作
return true;
}
#endregion
}
catch (Exception ex)
{
LogTextHelper.Error(ex);
MessageDxUtil.ShowError(ex.Message);
}
return false;
}
其中紅色部分就是我們新增的內容皂吮,我在代碼里面存儲當前登陸用戶的ID:LoginUserInfo.ID.ToString()戒傻。
這里的LoginUserInfo是窗體基類的一個屬性,這個屬性通過兩種方式獲得蜂筹,一個是通過用戶在調用窗體顯示前進行指定需纳,一種是通過基類自動把緩存里面的用戶對象賦值。
如下面的代碼就是界面基類BaseForm的部分代碼艺挪。
namespace WHC.Framework.BaseUI
{
/// <summary>
/// 常規(guī)界面基類
/// </summary>
public partial class BaseForm : DevExpress.XtraEditors.XtraForm, IFunction
{
public event EventHandler OnDataSaved;//子窗體數(shù)據(jù)保存的觸發(fā)
public BaseForm()
{
InitializeComponent();
//為了保證一些界面控件的權限控制和身份確認不翩,以及簡化操作,在界面初始化的時候麻裳,從緩存里面內容(如果存在的話)
//繼承的子模塊口蝠,也可以通過InitFunction()進行指定用戶相關信息
this.LoginUserInfo = Cache.Instance["LoginUserInfo"] as LoginUserInfo;
this.FunctionDict = Cache.Instance["FunctionDict"] as Dictionary<string, string>;
}
這些用戶和功能的信息來源于登陸主界面的時候,我們把它們進行了緩存津坑,方便基類窗體進行獲取妙蔗。
Portal.gc.LoginUserInfo = Portal.gc.ConvertToLoginUser(info);
Cache.Instance.Add("LoginUserInfo", Portal.gc.LoginUserInfo);//緩存用戶信息,方便后續(xù)處理
Cache.Instance.Add("FunctionDict", Portal.gc.FunctionDict);//緩存權限信息疆瑰,方便后續(xù)使用
第二種方式指定當前用戶信息的步驟眉反,是通過基類窗體的InitFunction函數(shù)進行指定狞谱。
/// <summary>
/// 初始化權限控制信息
/// </summary>
public void InitFunction(LoginUserInfo userInfo, Dictionary<string, string> functionDict)
{
if (userInfo != null)
{
this.LoginUserInfo = userInfo;
}
if (functionDict != null && functionDict.Count > 0)
{
this.FunctionDict = functionDict;
}
}
手工指定當前用戶信息的調用代碼如下所示。
private void btnAddNew_Click(object sender, EventArgs e)
{
FrmEditCustomer dlg = new FrmEditCustomer();
dlg.InitFunction(base.LoginUserInfo, base.FunctionDict);//該步驟省略也可以禁漓,用戶信息以通過基類緩存進行獲取
if (DialogResult.OK == dlg.ShowDialog())
{
BindData();
}
}
一般情況下跟衅,我們建議采用第一種,不用多余的代碼進行設置指定播歼,只需要在登錄的時候伶跷,把它放到緩存里面即可,這樣界面基類實例化的時候秘狞,就會自動獲取用戶信息了叭莫,這個操作類似于Web領域里面的Session操作,只要存儲/獲取的鍵值保存一致即可烁试。
好了雇初,我們前面說到,保存的時候减响,是保存當前用戶的ID信息靖诗,那么我們在列表展示的時候,默認就會展示用戶的ID信息而已支示,得到的界面效果如下所示刊橘。
我們?yōu)榱烁谜故緝热荩托枰獙τ脩鬒D的數(shù)據(jù)進行轉義颂鸿。
由于DevExpress有這樣對每行記錄進行轉義的操作促绵,我們在列表界面上添加一個轉義函數(shù)。
this.winGridViewPager1.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(gridView1_CustomColumnDisplayText);
數(shù)據(jù)轉義函數(shù)里面涉及到對權限系統(tǒng)模塊的引用(我們需要把ID轉義為FullName(用戶全名))嘴纺,我們把權限模塊的DLL引用包含進來即可(因為權限管理模塊是所有界面模塊都可以使用的)败晴。
然后在這個函數(shù)里面對當前的Creator進行轉義。
void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
{
if (e.Column.ColumnType == typeof(DateTime))
{
string columnName = e.Column.FieldName;
if (e.Value != null)
{
if (Convert.ToDateTime(e.Value) <= Convert.ToDateTime("1900-1-1"))
{
e.DisplayText = "";
}
else
{
e.DisplayText = Convert.ToDateTime(e.Value).ToString("yyyy-MM-dd HH:mm");//yyyy-MM-dd
}
}
}
else if (e.Column.FieldName == "Creator")
{
if (e.Value != null)
{
e.DisplayText = BLLFactory<User>.Instance.GetFullNameByID(e.Value.ToString().ToInt32());
}
}
}
然后復制文件栽渴,重新運行主程序即可看到如下界面所示尖坤。
至此,我們本小節(jié)已經完成了熔萧,登陸用戶信息的記錄和轉義的操作了糖驴,當然我們系統(tǒng)模塊里面僚祷,可能還有很多地方需要用到用戶信息的或者角色信息的佛致,這個例子只是一個拋磚引玉的操作。
循序漸進開發(fā)WInform項目--系列文章導引:
循序漸進開發(fā)WinForm項目(6)--開發(fā)使用混合式Winform模塊
循序漸進開發(fā)WinForm項目(5)--Excel數(shù)據(jù)的導入導出操作
循序漸進開發(fā)WinForm項目(4)--Winform界面模塊的集成使用
循序漸進開發(fā)WinForm項目(3)--Winform界面層的項目設計
循序漸進開發(fā)WinForm項目(2)--項目代碼的分析
循序漸進開發(fā)WinForm項目(1) --數(shù)據(jù)庫設計和項目框架的生成