public partial classfrmMain : RibbonForm {
MailType currentMailType =MailType.Inbox;
ModulesNavigator modulesNavigator;
internalFilterColumnsManager FilterColumnManager;
ZoomManager zoomManager;
List<BarItem> AllowCustomizationMenuList = new List<BarItem>();
publicfrmMain() {
InitializeComponent();
rpcSearch.Text =TagResources.SearchTools;
InitNavBarGroups();//初始化NarBarGroups,主要是给左侧的Group们的Tag绑定要在右侧Module中加载的页面
SkinHelper.InitSkinGallery(rgbiSkins);//初始化主题,在rgbiSkins中加载主题列表
RibbonButtonsInitialize();//初始化Ribbon中的控件们
modulesNavigator = new ModulesNavigator(ribbonControl1, pcMain);//初始化单元导航组件(ModulesNavigator)
zoomManager = new ZoomManager(ribbonControl1, modulesNavigator, beiZoom);//初始化伸缩管理组件
modulesNavigator.ChangeGroup(navBarControl1.ActiveGroup, this);//上面的InitNavBarGroups初始化了左侧的Group,现在切换到第一个分组
NavigationInitialize();//初始化导航控件
SetPageLayoutStyle();//设置页面的布局样式
}
----上面是主页面的构造函数,有个印象就好,这里要讲的是切换分组时要用到反射的情况,下面也是此类中的一些关键方法,只讲重点----
voidInitNavBarGroups() {
nbgMail.Tag = new NavBarGroupTagObject("Mail", typeof(DevExpress.MailClient.Win.Mail));
nbgCalendar.Tag = new NavBarGroupTagObject("Calendar", typeof(DevExpress.MailClient.Win.Calendar));
nbgContacts.Tag = new NavBarGroupTagObject("Contacts", typeof(DevExpress.MailClient.Win.Contacts));
nbgFeeds.Tag = new NavBarGroupTagObject("Feeds", typeof(DevExpress.MailClient.Win.Feeds));
nbgTasks.Tag = new NavBarGroupTagObject("Tasks", typeof(DevExpress.MailClient.Win.Tasks));
}
//切换左侧分组的操作,获取Group中应该加载的用户控件data,一般是列表之类的形式,连同分组e.Group作为参数传递过去,执行后续操作
private void navBarControl1_ActiveGroupChanged(objectsender, DevExpress.XtraNavBar.NavBarGroupEventArgs e) {
object data =GetModuleData((NavBarGroupTagObject)e.Group.Tag);
modulesNavigator.ChangeGroup(e.Group, data);
}
protected objectGetModuleData(NavBarGroupTagObject tag) {
if(tag == null) return null;
if (tag.ModuleType == typeof(DevExpress.MailClient.Win.Calendar)) returnucCalendar1;
if(tag.ModuleType == typeof(DevExpress.MailClient.Win.Feeds)) returnnavBarControl2;
if(tag.ModuleType == typeof(DevExpress.MailClient.Win.Tasks)) returnnbgTasks;
return null;
}
---------------------------------N多代码省略-------------------------------------
}
public classNavBarGroupTagObject {
string name;//单元名称
Type moduleType;//单元类型
BaseModule module;//单元,由父类定义
public NavBarGroupTagObject(stringname, Type moduleType) {
this.name =name;
this.moduleType =moduleType;
module = null;
}
public string Name { get { returnname; } }
public Type ModuleType { get { returnmoduleType; } }
publicBaseModule Module {
get { returnmodule; }
set { module =value; }
}
}
- 由于不管切换到那个分组,主页面总有一个单元,所以定义一个CurrentModule;
- 导航,所以定义一个ribbon,即最上面的RibbonControl 控件;
- 单元是动态加载到Panel中的,所以定义了一个panel,存放单元;
//主框架,单元导航组件(包含有一个RibbonControl和一个PanelControl)
public classModulesNavigator
{
/// <summary>
///当前组件中的单元,位于panel中
/// </summary>
publicBaseModule CurrentModule
{
get{
if (panel.Controls.Count == 0) //这里需要判断一下,是因为初始状态下panel里面没有控件,是经后面反射动态加载进去的
return null;
return panel.Controls[0] asBaseModule;
}
}
RibbonControl ribbon;
PanelControl panel;
publicModulesNavigator(RibbonControl ribbon, PanelControl panel)
{
this.ribbon =ribbon;
this.panel =panel;
}
/// <summary>
///切换NavBarControl中分组所执行的操作:①跟NavBarGroup对应的RibbonPage才可以显示②在Panel中加载Tag对象中的Module
/// </summary>
/// <param name="group">NavBarControl中切换到的分组</param>
/// <param name="moduleData">只在第一次加载时用到,注意这里不是单元中数据,而是左侧Group中应该加载的用户控件</param>
public void ChangeGroup(NavBarGroup group, objectmoduleData)
{
bool allowSetVisiblePage = true;
NavBarGroupTagObject groupObject = group.Tag as NavBarGroupTagObject;//把Tag中绑定的对象取出来
if (groupObject == null) return;//检查下group中tag属性有没有绑定对象,没有的话就不执行后面操作了
#region 判断哪些RibbonPage需要显示,放到deferredPagesToShow序列中(延期显示的Page们)List<RibbonPage> deferredPagesToShow = new List<RibbonPage>();
foreach (RibbonPage page inribbon.Pages)
{
if (!string.IsNullOrEmpty(string.Format("{0}", page.Tag)))
{
bool isPageVisible =groupObject.Name.Equals(page.Tag);
//要使Ribbon中的Page显示,需要满足如下两个条件:
//①当前选中分组的Tag属性绑定的对象的name属性值跟Ribbon中page的Tag属性值相等
//②Ribbon中的page的Visible==True
if (isPageVisible != page.Visible &&isPageVisible)
deferredPagesToShow.Add(page);
elsepage.Visible =isPageVisible;
}
if (page.Visible &&allowSetVisiblePage)
{
ribbon.SelectedPage = page;//跟group对应的page可以显示
allowSetVisiblePage = false;
}
}
#endregion
#region 第一次加载 (InitModule)
bool firstShow = groupObject.Module == null;//是否是第一次Show,第一次加载时Module为空
if(firstShow)
{
if (SplashScreenManager.Default == null)//启动画面管理:如果没有默认的,用wfMain做等待窗口
SplashScreenManager.ShowForm(ribbon.FindForm(), typeof(CN_Standards.ISPET.Win.Forms.wfMain), false, true);
ConstructorInfo constructorInfoObj = groupObject.ModuleType.GetConstructor(Type.EmptyTypes);//获得单位中没有参数的那个构造函数(一般都只有一个无参构造函数)
if (constructorInfoObj != null)
{
groupObject.Module = constructorInfoObj.Invoke(null) as BaseModule;//关键地方哦,用反射获得分组绑定对象中的单元
groupObject.Module.InitModule(ribbon, moduleData);//这里是初始化Module对应的那个Group中的用户控件,每个Module中初始化有差别
}
if (SplashScreenManager.Default != null)//不为空,这里的moduleData为主页面,此方法为主页面构造函数中的那个ChangeGroup方法
{
Form frm = moduleData as Form;//可以把单元中的moduleData转换成Form,
if (frm != null)
SplashScreenManager.CloseForm(false, 2000, frm);//延迟2秒后关闭等待窗口,打开主页面
elseSplashScreenManager.CloseForm();
}
}
#endregion
#region 让deferredPagesToShow序列中的RibbonPage显示出来,并让第一个被选中
foreach (RibbonPage page indeferredPagesToShow)
{//让跟group对应的page集合都显示出来
page.Visible = true;
}
foreach (RibbonPage page inribbon.Pages)
{//选中第一个关联的page
if(page.Visible)
{
ribbon.SelectedPage =page;
break;
}
}
#endregion
#region 再次加载以及离开此分组 (HideModule、ShowModule)
if (groupObject.Module != null)
{//清空panel,再次把groupObject.Module填充到panel中
if (panel.Controls.Count > 0)
{
BaseModule currentModule = panel.Controls[0] asBaseModule;
if (currentModule != null)
currentModule.HideModule();//在各个Module中执行
}
panel.Controls.Clear();
panel.Controls.Add(groupObject.Module);
groupObject.Module.Dock = DockStyle.Fill;//填充满
groupObject.Module.ShowModule(firstShow);//显示单元,firstShow可能等于true,也可能是false
}
#endregion}
}
{
base.InitModule(manager, data);//执行父类的初始化操作,就是这些Module有那些相同操作。。有点废话
EditorHelper.InitPriorityComboBox(repositoryItemImageComboBox1);//初始化重要性设置下拉框
this.ribbon = manager as RibbonControl;
ucMailViewer1.SetMenuManager(manager);
ShowAboutRow();
}
internaloverridevoid ShowModule(bool firstShow) {
base.ShowModule(firstShow);
if(firstShow) {
filterCriteriaManager =new FilterCriteriaManager(gridView1);
filterCriteriaManager.AddBarItem(OwnerForm.ShowUnreadItem, gcIcon, "[Read] = 0");
filterCriteriaManager.AddBarItem(OwnerForm.ImportantItem, gcPriority, "[Priority] = 2");
filterCriteriaManager.AddBarItem(OwnerForm.HasAttachmentItem, gcAttachment, "[Attachment] = 1");
filterCriteriaManager.AddClearFilterButton(OwnerForm.ClearFilterItem);
SetPriorityMenu();
SetDateFilterMenu();
OwnerForm.FilterColumnManager.InitGridView(gridView1);
} else {
lockUpdateCurrentMessage =false;//解除锁定
FocusRow(focusedRowHandle);//不是首次加载,选中上次移开时焦点所在行
}
gridControl1.Focus();
}
internaloverridevoid HideModule() {
lockUpdateCurrentMessage =true;//锁定
focusedRowHandle = gridView1.FocusedRowHandle;//保存焦点所在行
}
操作挺复杂的,只看我们想看的,可以看到ShowModule分为初次加载和非初次加载,初次加载时一堆操作,非初次加载,只是恢复了上次的状态;HideModule就简单了,保存状态即可。不用加载主页面时加载太多数据,也不用每次切换分组都重复加载数据,提高了系统的速度,增加了用户体验,维护也方便了很多。
好了,就先总结这么多了,其他的再慢慢总结。。详细代码就看DevExpress的第一个WinForm示例了,就不提供链接了。