XAF之创建高级Information Panel

在XAF的帮助文档中的topic为How to: Create Information Panels(http://documentation.devexpress.com/#Xaf/CustomDocument3309) 讲述了怎样创建InfoPanel,如图:


该主题涉及了自定义模版的较高级的应用,基于FeatureCenter的例子,下面讲述一下怎样创建一个高级InfoPanel,效果如图:


该例子的代码基本来自FeatureCenter,修正了其中的几个bug,根据自己的理解加入了注释。

1.将MainForm模版添加到Model.Win工程下

 %PROGRAMFILES%\DevExpress 2011.2\eXpressApp Framework\Sources\FrameTemplates 下找到MainForm的几个文件,复制到你的Model.Win下。并添加到工程。


2.使用视图设计器打开MainForm,添加SplitContainerControl 

viewSitePanel 添加到SplitContainerControl的Panel1中,然后设置SplitContainerControl的Dock属性为Fill,这部分操作帮助文档讲得很详细,不详述。

这里要注意的是帮助文档上没有说的两点:

1.SplitContainerControl的FixedPanel属性设置为Panel2,这样在缩放窗口时保证Panel2大小固定,更为美观;

2.SplitContainerControl的PanelVisibility属性设置为Panel1,这样通常情况下主窗口仅显示panel1,否则在不使用InfoPanel的窗口中会出现难看的空白分割线


3.继承一个IFrameTemplate接口,用于操作SplitContainerControl

using DevExpress.ExpressApp.Templates;
//... 
public interface IInfoPanelTemplateWin : IFrameTemplate {        
    DevExpress.XtraEditors.SplitContainerControl SplitContainer { get; }
}

若自定义模版添加了其他控件,也需要定义一个类似接口获取这些新控件的引用。

在我们添加的MainForm中添加代码,使MainForm继承实现IInfoPanelTemplateWin接口

public partial class MainForm : MainFormTemplateBase, IDockManagerHolder, ISupportMdiContainer, 
    ISupportClassicToRibbonTransform, IInfoPanelTemplateWin
{
    //... 
    public DevExpress.XtraEditors.SplitContainerControl SplitContainer {
        get { return splitContainerControl1; }
    }
}
为了支持MDI,还要修改Mainform的 UpdateMdiModeDependentProperties 方法:

public partial class MainForm : MainFormTemplateBase, IDockManagerHolder, ISupportMdiContainer, 
    ISupportClassicToRibbonTransform, IInfoPanelTemplateWin 
{
    //... 
    protected override void UpdateMdiModeDependentProperties() {
        //viewSitePanel.Visible = !isMdi; 
        splitContainerControl1.Visible = !isMdi;
        //... 
    }
}
4.修改Program.cs,使XAF使用自定义的模版而不是默认Mainform模版

static void Main()
        {
//...
            winApplication.CreateCustomTemplate += new EventHandler<CreateCustomTemplateEventArgs>(xafApplication_CreateCustomTemplate);
//...
        }
        static void xafApplication_CreateCustomTemplate(object sender, CreateCustomTemplateEventArgs e)
        {
            if (e.Context.Name == TemplateContext.ApplicationWindow)
            {
                e.Template = new DevExpress.ExpressApp.Win.CustomTemplates.MainForm();
            }
        }

5.继承CustomizeTemplateViewControllerBase,实现其虚拟方法

  • AddControlsToTemplateCore(TemplateType template)
    当Controller激活时,初始化控件,并添加到Template
  • RemoveControlsFromTemplateCore(TemplateType template)
    当Controller禁用时,删除控件
  • UpdateControls(View view)
    当View改变时,更新控件
  • UpdateControls(object currentObject)
     View的当前object改变时,更新控件

下面直接给出代码,查看代码及注释应该能理解,稍做修改就能用于自己的场景。

--------------------------------------InfoPanelsViewControllerBase<TemplateType>-------------------------------------------------------

/// <summary>
    /// InfoPanelsViewControllerBase类继承自CustomizeTemplateViewControllerBase
    /// 并实现了其UpdateControls(View view),UpdateControls(object currentObject)方法
    /// 其他方法和Control相关,故在InfoPanelsViewController中实现
    /// 本基类放在Module中,故只实现了对象相关的逻辑:代表InfoPanel的relatedViewFrame和
    /// PopupWindowShowAction按钮逻辑及显示文本的逻辑。
    /// GetInfoText()获取要显示的文本
    /// CreateRelatedViewControl()创建InfoPanel的Frame
    /// </summary>
    /// <typeparam name="TemplateType"></typeparam>
    public abstract class InfoPanelsViewControllerBase<TemplateType> : CustomizeTemplateViewControllerBase<TemplateType> where TemplateType : IFrameTemplate
    {
        private PopupWindowShowAction action;
        private Frame relatedViewFrame;
        //获取ListView的当前TestObject的Name
        private string GetInfoText()
        {
            string currentObjectRelatedInfo;
            if (View is ListView && View.CurrentObject == null)
            {
                currentObjectRelatedInfo = "Empty";
            }
            else
            {
                currentObjectRelatedInfo =  ((TestObject)View.CurrentObject).Name;
            }
            return currentObjectRelatedInfo;
        }
        //点击My Action弹出DetailView
        private void action_CustomizePopupWindowParams(object sender, CustomizePopupWindowParamsEventArgs e)
        {
            IObjectSpace objectSpace = Application.CreateObjectSpace();
            DetailView detailView = Application.CreateDetailView(objectSpace, objectSpace.GetObject(View.CurrentObject));
            e.View = detailView;
            e.Context = TemplateContext.PopupWindow;
        }
        private void view_ControlsCreated(object sender, EventArgs e)
        {
            ((View)sender).ControlsCreated -= new EventHandler(view_ControlsCreated);
            if (relatedViewFrame != null && relatedViewFrame.Template is ISupportStoreSettings)
            {
                ISupportStoreSettings storeSettings = (ISupportStoreSettings)relatedViewFrame.Template;
                storeSettings.SetSettings(Application.GetTemplateCustomizationModel(relatedViewFrame.Template));
                storeSettings.ReloadSettings();
            }
        }
        private void View_ModelSaved(object sender, EventArgs e)
        {
            if (relatedViewFrame != null && relatedViewFrame.Template is ISupportStoreSettings)
            {
                ((ISupportStoreSettings)relatedViewFrame.Template).SaveSettings();
            }
        }
        protected abstract void SetInfoTextToControls(string text);
        //创建Info Panel的Detail视图
        protected object CreateRelatedViewControl()
        {
            if (relatedViewFrame == null)
            {
                #region 这部分代码展示了Frame和Template,ObjectSpace和View的关系
                //为Frame赋值后必须调用CreateTemplate方法创建Template
                relatedViewFrame = Application.CreateFrame(TemplateContext.NestedFrame);
                relatedViewFrame.CreateTemplate();
                IObjectSpace objectSpace = Application.CreateObjectSpace();
                DetailView view = Application.CreateDetailView(objectSpace, "TestObject_DetailView_Copy", false, objectSpace.GetObject(View.CurrentObject));
                view.ControlsCreated += new EventHandler(view_ControlsCreated);
                view.AllowEdit["Demo"] = false;
                relatedViewFrame.SetView(view);
                #endregion
            }
            else
            {
                if (NeedRecreateRelatedViewFrameTemplate)
                {
                    relatedViewFrame.View.BreakLinksToControls();
                    relatedViewFrame.SetTemplate(null);
                    relatedViewFrame.CreateTemplate();
                }
            }
            return relatedViewFrame.Template;
        }

        protected override void UpdateControls(View view)
        {
            SetInfoTextToControls(GetInfoText());
        }
        protected override void UpdateControls(object currentObject)
        {
            SetInfoTextToControls(GetInfoText());
            if (relatedViewFrame != null)
            {
                //若不刷新ObjectSpace,则无法及时显示修改的记录
                relatedViewFrame.View.ObjectSpace.Refresh();
                relatedViewFrame.View.CurrentObject = currentObject == null ? null : relatedViewFrame.View.ObjectSpace.GetObject(currentObject);
            }
        }
        protected override void OnActivated()
        {
            base.OnActivated();
            View.ModelSaved += new EventHandler(View_ModelSaved);
        }
        protected override void OnDeactivated()
        {
            base.OnDeactivated();
            View.ModelSaved -= new EventHandler(View_ModelSaved);
        }

        public InfoPanelsViewControllerBase()
        {
            TargetObjectType = typeof(TestObject);
            //该Action的Category为ContextActions,该ActionContainer将在InfoPanelsViewController创建
            action = new PopupWindowShowAction(this, "ContextAction", "ContextActions");
            action.Caption = "My Action";
            action.SelectionDependencyType = SelectionDependencyType.RequireSingleObject;
            action.CustomizePopupWindowParams += new CustomizePopupWindowParamsEventHandler(action_CustomizePopupWindowParams);
            RegisterActions(action);
        }
        protected virtual bool NeedRecreateRelatedViewFrameTemplate
        {
            get { return false; }
        }
    }


--------------------------------------InfoPanelsViewControllerBase<TemplateType>-------------------------------------------------------

--------------------------------------InfoPanelsViewController-------------------------------------------------------

/// <summary>
    /// InfoPanelsViewController放置于Module.Win中,继承了InfoPanelsViewControllerBase
    /// 实现控件相关逻辑;实现了AddControlsToTemplateCore(IInfoPanelTemplateWin template)
    /// 和RemoveControlsFromTemplateCore(IInfoPanelTemplateWin template)
    /// 将文本,按钮,relatedView放置于GroupControl中分组显示
    /// </summary>
    public class InfoPanelsViewController : InfoPanelsViewControllerBase<IInfoPanelTemplateWin>
    {
        #region 创建模版上要显示的控件
        private GroupControl textPanel;
        private GroupControl actionConainersPanel;
        private GroupControl relatedViewPanel;
        private LabelControl literal;
        //若SplitContainerControl的Panel2中不含控件,则隐藏Panel2
        //由于自定义MainForm的Template后,所有MainForm都使用该模版
        //若不控制SplitContainerControl的显示/隐藏,则会影响其他不需要多面板的
        //Form,导致其他主Form也出现SplitContainerControl的分割线,使画面很难看
        private void UpdateInfoPanelVisibility(SplitContainerControl splitContainer)
        {
            splitContainer.PanelVisibility = splitContainer.Panel2.Controls.Count > 0 ? SplitPanelVisibility.Both : SplitPanelVisibility.Panel1;
        }
        private void EnsureControls()
        {
            if (textPanel == null)
            {
                CreateTextPanel();
                CreateActionContainerPanel();
                CreateRelatedViewPanel();
            }
        }
        private void CreateRelatedViewPanel()
        {
            relatedViewPanel = CreateGroupControl("View Panel");
            System.Windows.Forms.Control viewControl = (System.Windows.Forms.Control)CreateRelatedViewControl();
            viewControl.Dock = System.Windows.Forms.DockStyle.Top;
            relatedViewPanel.Controls.Add(viewControl);
        }
        //在代码中创建一个ActionContainer
        private void CreateActionContainerPanel()
        {
            actionConainersPanel = CreateGroupControl("Action Panel");
            ButtonsContainer actionContainer = new ButtonsContainer();
            actionContainer.Dock = System.Windows.Forms.DockStyle.Top;
            actionContainer.ContainerId = "ContextActions";
            actionConainersPanel.Controls.Add(actionContainer);
            IDynamicContainersTemplate template = Frame.Template as IDynamicContainersTemplate;
            if (template != null)
            {
                template.RegisterActionContainers(new[] { actionContainer });
            }
        }
        private void CreateTextPanel()
        {
            textPanel = CreateGroupControl("Text Panel");
            textPanel.Padding = new System.Windows.Forms.Padding(6);
            literal = new LabelControl();
            literal.AllowHtmlString = true;
            literal.Dock = System.Windows.Forms.DockStyle.Top;
            literal.AutoSizeMode = LabelAutoSizeMode.Vertical;
            textPanel.Controls.Add(literal);
        }
        private GroupControl CreateGroupControl(string caption)
        {
            GroupControl panel = new GroupControl();
            panel.AutoSize = true;
            panel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
            panel.Dock = System.Windows.Forms.DockStyle.Top;
            panel.Text = caption;
            return panel;
        }

        protected override void SetInfoTextToControls(string text)
        {
            if (literal != null)
            {
                literal.Text = text;
            }
        }
        #endregion
        #region 这两个方法继承自CustomizeTemplateViewControllerBase,在Controller激活/禁用时添加/删除控件
        protected override void AddControlsToTemplateCore(IInfoPanelTemplateWin template)
        {
            EnsureControls();
            template.SplitContainer.Panel2.Controls.Add(relatedViewPanel);
            template.SplitContainer.Panel2.Controls.Add(actionConainersPanel);
            template.SplitContainer.Panel2.Controls.Add(textPanel);
            UpdateInfoPanelVisibility(template.SplitContainer);
        }
        protected override void RemoveControlsFromTemplateCore(IInfoPanelTemplateWin template)
        {
            template.SplitContainer.Panel2.Controls.Remove(relatedViewPanel);
            template.SplitContainer.Panel2.Controls.Remove(actionConainersPanel);
            template.SplitContainer.Panel2.Controls.Remove(textPanel);
            UpdateInfoPanelVisibility(template.SplitContainer);
            textPanel = null;
            actionConainersPanel = null;
            literal = null;
        }
        #endregion
        public InfoPanelsViewController():base()
        {
            DevExpress.ExpressApp.Actions.SimpleAction showHideAction =
                new DevExpress.ExpressApp.Actions.SimpleAction(this, "ShowHideInfoPanel", DevExpress.Persistent.Base.PredefinedCategory.View);
            showHideAction.Execute += new DevExpress.ExpressApp.Actions.SimpleActionExecuteEventHandler(showHideAction_Execute);
        }
        void showHideAction_Execute(object sender, DevExpress.ExpressApp.Actions.SimpleActionExecuteEventArgs e)
        {
            SplitContainerControl splitContainer = ((IInfoPanelTemplateWin)Frame.Template).SplitContainer;
            splitContainer.PanelVisibility = splitContainer.PanelVisibility == DevExpress.XtraEditors.SplitPanelVisibility.Both ? DevExpress.XtraEditors.SplitPanelVisibility.Panel1 : DevExpress.XtraEditors.SplitPanelVisibility.Both;
        }
    }


--------------------------------------InfoPanelsViewController-------------------------------------------------------



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值