C# C/S结构数据库系统框架详解

自发布《多文档界面(MDI)系统框架-C#完整版》后又有了新想法,就是再写个C#版C/S结构系统框架。
因时间关系断断续续写了很久。借周日机会,我将源代码整理好再写些说明文档发布出来,希望给大家
带来学习机会。

   特别声明的是: C/S结构系统框架是优化和改编自几个大型系统,是经历过考验和实际应用的。希望大家好好珍惜。这个框架有很多学习要点,提醒大家不仅仅是下载代码而应该去好好研究,甚至阅读每一行代码每一个模块每一个细节! 你学会了它也许将来作为一个优秀架构师需要设计同样一个系统时,这时你用上它,不是事半功倍么?

另外,请尊重作者版权,写一个框架的确需要大量时间和精力。程序员有个共性是写作永无止境,虽是深夜2点,但我们仍在思考,仍在写作! 眼睛睡觉了但思维和创作动力仍在冗奋中,作为一个程序员的你,我说的对吗?有同样的感受吗? 所以:转载时请注明本文来自易学网www.vjsdn.net!

言归正传,接下来讲解系统框架实现过程。

首先看几个图对框架有个初步认识。

1.登陆窗体

准备登录窗体

如通过验证用户,则加载MDI主窗体,留意图片内的动态消息:
正在初始化用户界面,请稍候.

登录窗体是多数应用程序的入口,在进入系统前需要用户验证。请看实现过程:

2.MDI主窗体

 

登录成功后显示MDI主窗体.
图片为测试模块II的主界面.

登录成功后显示MDI主窗体.
图片为系统管理模块的主界面.

3.关于程序/作者

 

4.解决方案

 

用代码实现登录到加载MDI主窗体.

1.程序入口代码:

 

代码
    
    
static class Program
{
[STAThread]
static void Main()
{
// 捕获系统所产生的异常。
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);

SystemConfig.ReadSettings();
// 读取系统设置
bllService.SetDataBasePath(); // 因用到Access,指定一个MDB文件

Process instance
= SingletonProgram.GetRunningInstance();
if (instance != null ) Msg.Warning( " 程序已经运行. " );

if ((instance != null ) && ( ! SystemConfig.CurrentConfig.AllowRunMultiInstance))
{
SingletonProgram.HandleRunningInstance(instance);
// Active instance
return ;
}

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(
false );

// 注意:先打开登陆窗体,如登陆成功后再正式运行程序(MDI 主窗体)
// 学会这种写法。
if (AppEntry.Login())
Application.Run(AppEntry.MainForm);
else
Application.Exit();
}

private static void Application_ThreadException( object sender, ThreadExceptionEventArgs e)
{
Msg.ShowException(e.Exception);
}
}

转载请注明来自易学网 www.vjsdn.net 易学原创作品

留意这段代码:

   
   
if (AppEntry.Login())
Application.Run(AppEntry.MainForm);
else
Application.Exit();

 

调用AppEntry类表态方法Login(),如登录成功,此时已经创建MainForm实例,则运行主窗体.

AppEntry类是个公共类,仅定义登录方法及MDI主窗体变量.
在登录窗体内用到该类.用户登录成功则创建frmMain实例.然后调用Application.Run(AppEntry.MainForm)方法.

2.AppEntry类,应用程序入口类.

代码
    
    
public class AppEntry
{
public static bool Login()
{
return frmLogin.TryLogin();
}

private static frmMain _mainForm = null ;
public static frmMain MainForm { get { return _mainForm; } set { _mainForm = value; } }
}

3.登录窗体源代码:

代码
    
    
public partial class frmLogin : Form
{
// 将构造器设为静态,防止外部创建实例
private frmLogin()
{
InitializeComponent();
}

/// <summary>
/// 打开登陆窗体,公开一个主静态方法
/// </summary>
/// <returns></returns>
public static bool TryLogin()
{
frmLogin form
= new frmLogin();
bool ret = form.ShowDialog() == DialogResult.OK;
return ret;
}

private void btnLogin_Click( object sender, EventArgs e)
{
// 调用业务层登录方法
bool ret = new bllUser().Login(txtUser.Text, txtPwd.Text);

if (ret)
{
// 登录成功创建主窗体
AppEntry.MainForm = new frmMain();

// 初始化主窗体(如加载模块,初始化用户界,加载系统参数)
// 在初始化同时login窗体会动态显示信息。
AppEntry.MainForm.InitUserInterface( new StatusLable( this .lblLoadingInfo));

this .DialogResult = DialogResult.OK;
this .Close(); // 关闭登陆窗体
}
else
{
Msg.Warning(
" 登录失败,请检查用户名和密码! " );
}
}

private void btnCancel_Click( object sender, EventArgs e)
{
this .Close();
}
}
转载请注明来自易学网 http:
// www.vjsdn.net/ 易学原创作品

 

这里需要调用业务层执行用户登录. 要学会将业务代码与界面代码分离.

   
   
// 调用业务层登录方法
bool ret = new bllUser().Login(txtUser.Text, txtPwd.Text);

if (ret)
{
.........

 

当登录成功,创建MDI主窗体实例,然后调用实例方法InitUserInterface.这时初始化主窗体.

   
   
// 初始化主窗体(如加载模块,初始化用户界,加载系统参数)
// 在初始化同时login窗体会动态显示信息。
AppEntry.MainForm.InitUserInterface( new StatusLable( this .lblLoadingInfo));

 

4.下面是MDI主窗体的代码:

代码
    
    
public partial class frmMain : Form
{
// 模块管理器实例
private ModuleManager _ModuleManager;

public frmMain()
{
InitializeComponent();
}

// 初始化用户接口
public void InitUserInterface(StatusLable splash)
{
this .SuspendLayout();

splash.UpdateMessage(
" 正在初始化用户界面,请稍候... " );
_ModuleManager
= new ModuleManager( this , xtraTabControl1); // 创建模块管理器
_ModuleManager.LoadModules(splash); // 加载可用模块

splash.UpdateMessage(
" 正在加载工具栏... " );
_ModuleManager.CreateNavBarButtons(
this .navBarControl1, this .menuStrip1); // 创建导航工具栏按钮

splash.UpdateMessage(
" 正在加载用户模块... " );

splash.UpdateMessage(
" 正在初始化数据... " );

splash.UpdateMessage(
" 加载完毕. " );

this .ResumeLayout();
}

/// <summary>
/// 显示由参数指定的模块
/// </summary>
public void ActiveModule( string moduleDisplayName)
{
foreach (XtraTabPage page in this .xtraTabControl1.TabPages)
{
if (page.Text.Equals(moduleDisplayName))
{
xtraTabControl1.SelectedTabPage
= page;
return ;
}
}
}

private void btnHelp_Click( object sender, EventArgs e)
{
new frmAboutVjsdn().ShowDialog();
}

private void btnClose_Click( object sender, EventArgs e)
{
this .Close();
}

private void btnAbout_Click( object sender, EventArgs e)
{
new frmAboutVjsdn().ShowDialog();
}
}
转载请注明来自易学网 http:
// www.vjsdn.net/ 易学原创作品

窗体类定义一个_ModuleManager变量,用于加载模块.请看ModuleManager详解.
InitUserInterface()方法是初始化主窗体方法.由frmLogin调用.

转载请注明来自易学网 http://www.vjsdn.net/ 易学原创作品

 

 

 

C# C/S结构数据库系统框架详解(二) ModuleManager详解[vjsdn]

一个大的应用程序由大量模块构成, 因人而异模块的理解和分类各有不同. 在C/S框架内我将模块(Module)定义为一个DLL程序(Class Library). 而每个DLL程序按业务分类. 如进销存系统我们可定义3个模块:采购模块(Purchase Module),销售模块(Sales Module)和库存模块(Inventory Module).而每个模块的业务代码封装在
DLL Class Library内. 则构成3个独立的DLL和一个可执行EXE文件. 如要细分还有公共模块(Common Module), 数据访问层(Data Access Layer Module),系统安全(System Security Module)和系统设置模块(System Setups Module)等模块. 这样就构成一个简单的多模块系统框架了.

C/S框架内定义了8个模块(DLL)和一个主程序(EXE).

从设计角度上讲模块也要分类,可分为系统模块和业务模块.

系统模块是框架组成部分,如Business.dll,Common.dll,DataAccess.dll,Library.dll,Models.dll.
业务模块封装核心业务,包括业务窗体,图片资源等信息. 如上所述的进销存系统:进,销,存3个模块为业务模块.

我们对模块有了初步认识. 由此可见一个系统是由很多模块构成的,而系统越大分的模块越多,模块越多程序越复杂和难以控制.当然安全问题也应运而生了.

假设A用户仅能使用采购模块(Purchase Module),另两个模块不可见, 在设计上我们可以这么做:
1.设计权限,隐藏其它两个模块.
2.在客户机仅发布exe和purchase.dll
3.其它设计.

假设不按业务独立模块,我想设计权限来隐藏其它两个模块是件复杂而危险的事. 可想而知你需要在每个窗体每个业务类都要判断A用户是否有Sales和Inventory的权限,成百上千种判断会使你疯狂!

但是只给客户机安装一个purchase.dll,即使在设计上不判断权限也用不着Sales和Inventory任何功能!

假设我们选择第2种方法, 因客户不同发布的dll也不同,这里牵涉到动态加载dll的问题!本文的重点就是介绍如何动态加载模块.下面且看相关源代码:

ModuleID类:模块编号,给每个模块一个唯一编号.

 

   
   
/// <summary>
/// 模块编号,给每个模块一个唯一编号.
/// </summary>
public enum ModuleID
{
None
= 0 ,
TestModule1
= 1 , // 测试模块1
TestModule2 = 2 , // 测试模块2
SystemManage = 3 , // 系统管理模块
}

 

模块信息类:实体类,封装与模块相关信息.

 

代码
    
    
/// <summary>
/// 模块信息类
/// </summary>
public class ModuleInfo
{
private Assembly _ModuleAssembly = null ;
private ModuleID _ModuleID = ModuleID.None;
private string _ModuleName = string .Empty;
private string _ModuleFile = string .Empty;

/// <summary>
/// 构造器
/// </summary>
public ModuleInfo(Assembly asm, ModuleID id, string name, string file)
{
_ModuleAssembly
= asm;
_ModuleFile
= file;
_ModuleID
= id;
_ModuleName
= name;
}

/// <summary>
/// 加载DLL文件后程序集指针
/// </summary>
public Assembly ModuleAssembly
{
get { return _ModuleAssembly; }
set { _ModuleAssembly = value; }
}

/// <summary>
/// 模块文件(*.dll)
/// </summary>
public string ModuleFile
{
get { return _ModuleFile; }
set { _ModuleFile = value; }
}

/// <summary>
/// 模块名称
/// </summary>
public string ModuleName
{
get { return _ModuleName; }
set { _ModuleName = value; }
}

/// <summary>
/// 模块编号
/// </summary>
public ModuleID ModuleID
{
get { return _ModuleID; }
set { _ModuleID = value; }
}
}

转载请注明来自易学网 www.vjsdn.net 易学原创作品

 

ModuleLoader:模块加载器. 通过ModuleLoader类动态加载模块dll, 将程序集Assembly保存在
_ModuleAssembly变量.

 

代码
    
    
/// <summary>
/// 模块加载器
/// </summary>
public class ModuleLoader
{
private string _ModuleFileName; // DLL 文件名
private frmModuleBase _ModuleMainForm; // 如果加載了模塊. 返回該模塊的主窗體對象.
private Assembly _ModuleAssembly;

public static readonly string MODULE_FILTER = " 易学网C/S系统框架模块|VJSDN C/S Modules|*.dll " ;
public static readonly string MODULE_PATH = Application.StartupPath;

public ModuleLoader()
{
//
}

/// <summary>
/// 模块所在的程序集
/// </summary>
public Assembly ModuleAssembly
{
get { return _ModuleAssembly; }
}

/// <summary>
/// 返回AssemblyModuleEntry,自定义模块特性
/// </summary>
public string GetCurrentModuleName()
{
return ModuleLoader.GetModuleEntry(_ModuleAssembly).ModuleName;
}

/// <summary>
/// 模块主窗体
/// </summary>
public frmModuleBase ModuleMainForm
{
get { return _ModuleMainForm; }
}

/// <summary>
/// 加载模块的菜单
/// </summary>
/// <param name="menuStrip"> 程序主窗体的菜单 </param>
public void LoadMenu(MenuStrip menuStrip)
{
if (_ModuleMainForm != null && _ModuleMainForm.GetModuleMenu() != null )
{
menuStrip.Items.Insert(menuStrip.Items.Count
- 1 , _ModuleMainForm.GetModuleMenu().Items[ 0 ]);
}
}

/// <summary>
/// 加载模块主方法
/// </summary>
/// <param name="moduleinfo"> 模块信息 </param>
/// <returns></returns>
public bool LoadModule(ModuleInfo moduleinfo)
{
_ModuleFileName
= moduleinfo.ModuleFile;
_ModuleAssembly
= moduleinfo.ModuleAssembly;
string entry = GetModuleEntryNameSpace(_ModuleAssembly);
if ( string .Empty == entry) return false ;

Form form
= (Form)_ModuleAssembly.CreateInstance(entry);
_ModuleMainForm
= null ;

if (form is IModuleBase)
_ModuleMainForm
= (frmModuleBase)form;

return _ModuleMainForm != null ;
}

/// <summary>
/// 获取模块列表,转换为ModuleInfo集合.
/// </summary>
public IList < ModuleInfo > GetModuleList()
{
try
{
string [] files = null ; // 模塊文件(*.dll)
IList < ModuleInfo > list = new List < ModuleInfo > ();

if (Directory.Exists(MODULE_PATH))
files
= Directory.GetFiles(MODULE_PATH, " *.dll " );

foreach ( string mod in files)
{
Assembly asm
= null ;
try
{
// .net framework dll
asm = Assembly.LoadFile(mod);
}
catch { continue ; }

ModuleID id
= GetModuleID(asm);
string name = GetCurrentModuleName();
if (id != ModuleID.None)
{
ModuleInfo m
= new ModuleInfo(asm, id, name, mod);
list.Add(m);
}
}

SortModule(list);
// 模塊排序.

return list;
}
catch (Exception ex)
{
Msg.ShowException(ex);
return null ;
}
}

/// <summary>
/// 获取程序集自定义特性。是否用户自定义模块由AssemblyModuleEntry特性确定。
/// </summary>
/// <returns></returns>
public AssemblyModuleEntry GetModuleEntry()
{
return ModuleLoader.GetModuleEntry(_ModuleAssembly);
}

/// <summary>
/// 判断加载的文件是否模块文件,因目录下可能有不同类别的DLL文件。
/// 判断DLL为模块的条件是检查Assembly特性。
/// </summary>
public bool IsModuleFile( string moduleFile)
{
try
{
Assembly asm
= Assembly.LoadFile(moduleFile);
return (ModuleLoader.GetModuleID(asm) != ModuleID.None);
}
catch { return false ; }
}

/// <summary>
/// 每一个模块对应一个XtraTabPage,然后將模块主窗体的Panel容器放置在XtraTabPage内。
/// 因此,所有加载的模块主窗体的Panel容器都嵌套在主窗体的XtraTabControl内。
/// </summary>
public void LoadGUI(XtraTabControl mainTabControl)
{
try
{
IModuleBase moduleBase
= _ModuleMainForm as IModuleBase;

Panel container
= moduleBase.GetContainer(); // 模块主窗体的Panel容器
if ( null != container)
{
container.Dock
= DockStyle.Fill;
XtraTabPage page
= new XtraTabPage();
page.Text
= this .GetCurrentModuleName();
page.Controls.Add(container);
mainTabControl.TabPages.Add(page);
}
}
catch (Exception ex) { Msg.ShowException(ex); }
}

/// <summary>
/// 模块排序
/// </summary>
/// <param name="list"></param>
public void SortModule(IList < ModuleInfo > list)
{
int i, j;
ModuleInfo temp;
bool done = false ;
j
= 1 ;
while ((j < list.Count) && ( ! done))
{
done
= true ;
for (i = 0 ; i < list.Count - j; i ++ )
{
if ((list[i] as ModuleInfo).ModuleID > (list[i + 1 ] as ModuleInfo).ModuleID)
{
done
= false ;
temp
= list[i];
list[i]
= list[i + 1 ];
list[i
+ 1 ] = temp;
}
}
}
}

#region 类公共表态方法

/// <summary>
/// 查找子菜单,深度搜索
/// </summary>
public static ToolStripMenuItem GetMenuItem(ToolStrip mainMenu, string menuName)
{
ToolStripItem[] items
= mainMenu.Items.Find(menuName, true );
if (items.Length > 0 && items[ 0 ] is ToolStripMenuItem)
return (ToolStripMenuItem)items[ 0 ];
else
return null ;
}

/// <summary>
/// 获取程序集自定义特性。是否用户自定义模块由AssemblyModuleEntry特性确定。
/// </summary>
public static AssemblyModuleEntry GetModuleEntry(Assembly asm)
{
AssemblyModuleEntry temp
= new AssemblyModuleEntry(ModuleID.None, "" , "" );
if (asm == null ) return temp;

object [] list = asm.GetCustomAttributes( typeof (AssemblyModuleEntry), false );
if (list.Length > 0 )
return (AssemblyModuleEntry)list[ 0 ];
else
return temp;
}

/// <summary>
/// 获取模块主窗体名字空间
/// </summary>
public static string GetModuleEntryNameSpace(Assembly asm)
{
return GetModuleEntry(asm).ModuleEntryNameSpace;
}

/// <summary>
/// 獲取模塊編號
/// </summary>
public static ModuleID GetModuleID(Assembly asm)
{
return ModuleLoader.GetModuleEntry(asm).ModuleID;
}

#endregion
}
转载请注明来自易学网 www.vjsdn.net 易学原创作品


 

模块控制类
1.管理ModuleLoader加载的模块.
2.动态创建菜单及导航条按钮.
3.将所有模块主窗体组合在XtraTabControl 控件内. 每个XtraTabPage对应一个模块.

 

代码
    
    
/// <summary>
/// 模块管理器
/// </summary>
public class ModuleManager
{
// 程序主窗体的TabControl,用于放置模块主窗体
private XtraTabControl _tabControlModules = null ;

// 程序主窗体
private Form _MDIMainForm = null ;

private static IList < ModuleInfo > _Modules = null ;

/// <summary>
/// 获取回载的模块
/// </summary>
public static IList < ModuleInfo > GetAvailableModules()
{
return _Modules;
}

/// <summary>
/// 构造器
/// </summary>
public ModuleManager(Form mdiMainForm, XtraTabControl tabControlModules)
{
_tabControlModules
= tabControlModules;
_MDIMainForm
= mdiMainForm;
}

/// <summary>
/// Navigator bar 导航条按鈕事件.
/// </summary>
public static void OnNavBarLinkClick( object sender, NavBarLinkEventArgs e)
{
if (e.Link.Item.Tag is ToolStripItem)
{
ToolStripItem item
= (ToolStripItem)(e.Link.Item.Tag);
if ( null != item) item.PerformClick(); // 執行菜單事件.
}
}

/// <summary>
/// 是否有子菜單.
/// </summary>
private bool IsSubMenuOwner(ToolStripItem item)
{
if (item is ToolStripMenuItem)
{
if (((ToolStripMenuItem)item).DropDownItems.Count > 0 )
return true ;
}
return false ;
}

/// <summary>
/// 由菜单创建导航条控件按钮
/// </summary>
private NavBarItem CreateNavBarItem(NavBarControl navBar, ToolStripItem item)
{
NavBarItem newItem
= new NavBarItem();
newItem.Caption
= item.Text;
newItem.Tag
= item; // 綁定一個菜單項,newItem.Click事件會使用這個菜單項
newItem.LinkClicked += new NavBarLinkEventHandler(ModuleManager.OnNavBarLinkClick);
navBar.Items.Add(newItem);
return newItem;
}

/// <summary>
/// 导航条控件按钮分组
/// </summary>
private NavBarGroup CreateNavBarGroup(NavBarControl navBar, string caption)
{
NavBarGroup group
= navBar.Groups.Add(); // 增加一個Button組.
group.Caption = caption; // 模塊的顯示名稱
group.LargeImageIndex = 0 ;
if (group.Caption.Equals( string .Empty)) group.Caption = " Unknown Name " ;
return group;
}

/// <summary>
/// 当点击导航条分组按钮时触发该事件
/// </summary>
private void OnActiveGroupChanged( object sender, DevExpress.XtraNavBar.NavBarGroupEventArgs e)
{
try
{
string moduleName = e.Group.Caption.ToString();
this .ActiveModule(moduleName);
}
catch (Exception ex) { Msg.ShowException(ex); }
}

/// <summary>
/// 显示指定的模块主窗体
/// </summary>
public void ActiveModule( string moduleDisplayName)
{
foreach (XtraTabPage page in this ._tabControlModules.TabPages)
{
if (page.Text.Equals(moduleDisplayName))
{
_tabControlModules.SelectedTabPage
= page;
return ;
}
}
}

/// <summary>
/// 创建导航条分组按钮 Navigator NavBarGroup
/// </summary>
/// <param name="navBar"> NavBarControl对象 </param>
/// <param name="moduleMenu"> 模块主菜单 </param>
/// <param name="moduleDisplayName"> 模块名称 </param>
public NavBarGroup CreateNavBarButton(NavBarControl navBar, ToolStripMenuItem moduleMenu, string moduleDisplayName)
{
navBar.ActiveGroupChanged
+= new NavBarGroupEventHandler(OnActiveGroupChanged);

NavBarGroup group
= CreateNavBarGroup(navBar, moduleDisplayName); // 根据模块名称创建Group
if (moduleMenu == null ) return group; // 组没有菜单则返回,实为一个空组无子按钮.

foreach (ToolStripItem menuItem in moduleMenu.DropDownItems)
{
if (menuItem is ToolStripSeparator) continue ;
if (IsSubMenuOwner(menuItem)) continue ;
if (menuItem.Enabled)
{
NavBarItem item
= CreateNavBarItem(navBar, menuItem);
item.SmallImageIndex
= 1 ; // Sub Function
group.ItemLinks.Add(item);
}
}
return group;
}

/// <summary>
/// 初始化NavBar控件.绑定组NavGroup.ActiveGroupChanged事件
/// </summary>
public void CreateNavBarButtons(NavBarControl navBar, MenuStrip mainMenu)
{
try
{
navBar.SuspendLayout();
navBar.Items.Clear();
navBar.Groups.Clear();
foreach (XtraTabPage page in this ._tabControlModules.TabPages)
{
// 取主窗体对应的顶级菜单
ToolStripMenuItem moduleMenu = FindMenuItemByText(mainMenu, page.Text);

if (moduleMenu != null && moduleMenu.Enabled) // 创建该模块的NavBarButton.
this .CreateNavBarButton(navBar, moduleMenu, page.Text);
}
navBar.ResumeLayout();
}
catch (Exception ex) { Msg.ShowException(ex); }
}

private ToolStripMenuItem FindMenuItemByText(MenuStrip mainMenu, string text)
{
foreach (ToolStripMenuItem item in mainMenu.Items)
if (item.Text == text) return (ToolStripMenuItem)item;
return null ;
}

/// <summary>
/// 加载模块主方法
/// </summary>
public void LoadModules(StatusLable msg)
{
try
{
ModuleLoader loader
= new ModuleLoader();
_Modules
= loader.GetModuleList(); // 從目錄裝載模塊
foreach (ModuleInfo m in _Modules) // 枚舉文件名列表.
{
if ( ! loader.LoadModule(m)) continue ;

msg.UpdateMessage(
" 正在加载: " + loader.GetCurrentModuleName());
loader.LoadGUI(_tabControlModules);
loader.LoadMenu(_MDIMainForm.MainMenuStrip);
loader.ModuleMainForm.MdiParent
= _MDIMainForm; // 设置模块主窗体的父窗体.
}
GC.Collect();
}
catch (Exception ex) { Msg.ShowException(ex); }
}
}
转载请注明来自易学网 www.vjsdn.net 易学原创作品

 

为了规范模块共有的特性,设计一个模块主窗体接口.

 

代码
    
    
/// <summary>
/// 模块主窗体接口
/// </summary>
public interface IModuleBase
{
ModuleID GetModuleID();
// 获取模块编号
ModuleInfo GetModuleInfo(); //
Panel GetContainer(); // 模块主窗体容器
MenuStrip GetModuleMenu();

void InitButton();
void InitMenu();
}
转载请注明来自易学网 www.vjsdn.net 易学原创作品

 

定义一个模块主窗体基类来实现这个接口.

 

代码
    
    
/// <summary>
/// 模块主窗体基类
/// </summary>
public partial class frmModuleBase : frmBase, IModuleBase
{
public frmModuleBase()
{
InitializeComponent();
}

#region IModuleBase Members

// 模块的主菜单
public virtual MenuStrip GetModuleMenu()
{
return null ;
}

// 模块编号
public virtual ModuleID GetModuleID()
{
return ModuleID.None;
}

// 模块信息
public virtual ModuleInfo GetModuleInfo()
{
return null ;
}

// 模块主窗体容器
public virtual Panel GetContainer()
{
return this .pnlContainer;
}

// 初始化按钮
public virtual void InitButton()
{
}

// 初始化菜单
public virtual void InitMenu()
{
}

#endregion
}
转载请注明来自易学网 www.vjsdn.net 易学原创作品


 


C# C/S结构数据库系统框架详解(三) 如何新建一个模块(InventoryModule)[vjsdn]

1. 新增一个Class Library项目,命名为vjsdn.CS3Layers_Framework.InventoryModule.
2. 在项目内新增一个Inherited Form,命名为frmModuleMain,按Add按钮,选择frmModuleBase基类.

3. 在ModuleID枚举新增一个枚举类型,命名为InventoryModule=4.

代码
      
      
/// <summary>

/// 模块编号

/// </summary>

public enum ModuleID

{

None
= 0 ,

TestModule1
= 1 ,

TestModule2
= 2 ,

SystemManage
= 3 ,

InventoryModule
= 4 // 库存模块

}


4. 展开项目的Properties结点,打开AssemblyInfo.cs文件, 加入下面代码:

     
     
[assembly: AssemblyModuleEntry(ModuleID.InventoryModule, " 库存模块 " , " vjsdn.CS3Layers_Framework.InventoryModule.frmModuleMain " )]

 

这步非常重要,需要指定ModuleID,模块名称和模块主窗体的名字空间. 模块名称需要与模块主窗体菜单的名字一致!请看第8步菜单名称.

5.在frmModuleMain窗体内加入一个menuStrip控件,修改一级菜单的Text属性为库存模块.另加两个子菜单为库存查询和库存盘点.

6.在frmModuleMain窗体pnlContainer控件内加两上按钮命名为btnQuery,btnChecking.分别在Click事件内
输入

     
     
MessageBox.Show((sender as Button).Text);

 

7.子菜单[库存查询]的Click事件设为btnQuery_Click
8.子菜单[库存盘点]的Click事件设为btnChecking_Click, 下图是窗体设计状态

9.重写GetModuleMenu方法

     
     
public override MenuStrip GetModuleMenu()
{
menuStrip1.Text
= " 库存模块 " ; // 与AssemblyModuleEntry.ModuleName定义相同
return this .menuStrip1;
}

 

设计后的代码:

代码
      
      
namespace vjsdn.CS3Layers_Framework.InventoryModule
{
// 库存模块主窗体
public partial class frmModuleMain : vjsdn.CS3Layers_Framework.Library.frmModuleBase
{
public frmModuleMain()
{
InitializeComponent();
}

public override MenuStrip GetModuleMenu()
{
menuStrip1.Text
= " 库存模块 " ; // 与AssemblyModuleEntry.ModuleName定义相同
return this .menuStrip1;
}

private void btnChecking_Click( object sender, EventArgs e)
{
MessageBox.Show((sender
as Button).Text);
}

private void btnQuery_Click( object sender, EventArgs e)
{
MessageBox.Show((sender
as Button).Text);
}
}
}

 

10.设置项目的output path为: ../Debug/, 所有编译的程序放在同一目录.

编译后运行:

图中有四个业务模块,库存模块是新增的.

 全部链接:
1.C/S结构数据库系统框架详解
http://www.vjsdn.com/bbs/bbsTopicDetails.aspx?pid=109201218

2.ModuleManager详解
http://www.vjsdn.com/bbs/bbsTopicDetails.aspx?pid=109201219

3.如何新建一个模块
http://www.vjsdn.com/bbs/bbsTopicDetails.aspx?pid=109201220

4.C/S结构数据库系统框架源代码
http://www.vjsdn.com/bbs/bbsTopicDetails.aspx?pid=109201221

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值