XAF之实现子导航栏

来源:互联网 发布:教育大数据app 编辑:程序博客网 时间:2024/05/08 18:42

点击导航栏某项,出现一个子导航栏,如图:


   实现原理其实很简单,主导航栏的"Navigation System"对应的也是一个DetailView,只不过这个DetailView包含一个Action类型的属性,如果不为该属性设计PropertyEditor,那么该项是无法通过UI编辑的,所以,说白了,就是为Action属性设计一个PropertyEditor。下面讲述一下如何完成这一任务:

1. 首先,定义两个Business类,一个NavigationObject代表图中主显示区的对象,注意包含了一个SingleChoiceAction和子项的集合。

public  class NavigationObject : BaseObject, INotifyPropertyChanged    {        private ItemsDisplayStyle defaultChildItemsDisplayStyle = ItemsDisplayStyle.List;        private NavigationStyle navigationStyle = NavigationStyle.NavBar;        private SingleChoiceAction action;        private bool isWebApplication;        private void action_Execute(object sender, SingleChoiceActionExecuteEventArgs e)        {            Console.WriteLine(string.Format("The '{0}' navigation item is selected", e.SelectedChoiceActionItem.Caption));        }        private void ProcessItem(NavigationItem item, ChoiceActionItemCollection choiceActionItemCollection, ModelNode parentModel)        {            object objectKey = Session.GetKeyValue(item);            IModelNavigationItem modelNavigaionItem = parentModel.AddNode<IModelNavigationItem>(objectKey.ToString());            FillNavigationItemModel(item, modelNavigaionItem);            ChoiceActionItem choiceActionItem = new ChoiceActionItem(modelNavigaionItem, item);            choiceActionItem.ImageName = item.ImageName;            choiceActionItemCollection.Add(choiceActionItem);            SortItems(item.Items);            foreach (NavigationItem childItem in item.Items)            {                ProcessItem(childItem, choiceActionItem.Items, (ModelNode)modelNavigaionItem);            }        }        private void FillNavigationItemModel(NavigationItem item, IModelNavigationItem modelNavigaionItem)        {            modelNavigaionItem.Caption = item.Name;            modelNavigaionItem.Index = item.Index;            if (item.ChildItemsDisplayStyle == DemoNavigationChildItemsDisplayStyle.Default)            {                modelNavigaionItem.ChildItemsDisplayStyle = item.NavigationObject.DefaultChildItemsDisplayStyle;            }            else            {                modelNavigaionItem.ChildItemsDisplayStyle = item.ChildItemsDisplayStyle == DemoNavigationChildItemsDisplayStyle.List ? ItemsDisplayStyle.List : ItemsDisplayStyle.LargeIcons;            }            modelNavigaionItem.ImageName = item.ImageName;        }        protected virtual void OnPropertyChanged(string propertyName)        {            if (PropertyChanged != null)            {                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));            }        }        protected override void OnLoaded()        {            base.OnLoaded();            BuildAction();        }        internal void BuildAction()        {            //B152525            Action.Items.Clear();            SortItems(NavigationItems);            ModelApplicationCreator creator = NavigationDemoWindowController.ModelCreatorInstance;            if (creator != null)            {                ModelNode modelNavigationItems = creator.CreateNode(Guid.NewGuid().ToString(), typeof(IModelNavigationItems));                foreach (NavigationItem item in NavigationItems)                {                    if (item.Parent == null)                    {                        ProcessItem(item, Action.Items, modelNavigationItems);                    }                }            }        }        private void SortItems(XPCollection<NavigationItem> items)        {            items.Sorting.Clear();            items.Sorting.Add(new SortProperty("Index", DevExpress.Xpo.DB.SortingDirection.Ascending));        }        public NavigationObject(Session session)            : base(session)        {            action = new SingleChoiceAction();            action.Caption = "Navigation";            action.Execute += new SingleChoiceActionExecuteEventHandler(action_Execute);        }        [Browsable(false), NonPersistent]        public bool IsWebApplication        {            get { return isWebApplication; }            set            {                isWebApplication = value;            }        }        [ImmediatePostData]        public ItemsDisplayStyle DefaultChildItemsDisplayStyle        {            get { return defaultChildItemsDisplayStyle; }            set            {                SetPropertyValue<ItemsDisplayStyle>("DefaultChildItemsDisplayStyle", ref defaultChildItemsDisplayStyle, value);                //OnPropertyChanged("Hint");            }        }        [ImmediatePostData]        public NavigationStyle NavigationStyle        {            get { return navigationStyle; }            set            {                SetPropertyValue<NavigationStyle>("NavigationStyle", ref navigationStyle, value);            }        }        //子导航的根节点        public SingleChoiceAction Action        {            get { return action; }        }        //子项的集合        [Association("NavigationObject-NavigationItems"), Aggregated]        public XPCollection<NavigationItem> NavigationItems        {            get { return GetCollection<NavigationItem>("NavigationItems"); }        }        public event PropertyChangedEventHandler PropertyChanged;    }

2.为其SingleChoiceAction属性实现PropertyEditor;

[PropertyEditor(typeof(SingleChoiceAction))]    public class NavigationActionContainerPropertyEditor : PropertyEditor    {        private NavigationActionContainer NavigationActionContainer        {            get { return (NavigationActionContainer)Control; }        }        private NavigationObject NavigationObject        {            get            {                return (NavigationObject)CurrentObject;            }        }        protected override object CreateControlCore()        {            return new NavigationActionContainer();        }        protected override void ReadValueCore()        {            NavigationActionContainer.Register((SingleChoiceAction)PropertyValue, NavigationObject.NavigationStyle);        }        protected override object GetControlValueCore()        {            return null;        }        public NavigationActionContainerPropertyEditor(Type objectType, IModelMemberViewItem info) : base(objectType, info) { }    }


3.实现要显示的子项类NavigationItem,其中Index属性是做排序和图标选择用途,该类没有特别的含义,只为了显示结果

public class NavigationItem : BaseObject, INotifyPropertyChanged    {        private string name;        private int index;        private DemoNavigationChildItemsDisplayStyle childItemsDisplayStyle;        private NavigationItem parent;        private NavigationObject navigationObject;        private string imageName;        private string GetEmptyImageName()        {            return Items.Count == 0 ? "BO_Unknown" : "BO_Folder";        }        protected virtual void OnPropertyChanged(string propertyName)        {            if (PropertyChanged != null)            {                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));            }        }        public NavigationItem(Session session) : base(session) { }        [ImmediatePostData]        public DemoNavigationChildItemsDisplayStyle ChildItemsDisplayStyle        {            get { return childItemsDisplayStyle; }            set            {                SetPropertyValue<DemoNavigationChildItemsDisplayStyle>("ChildItemsDisplayStyle", ref childItemsDisplayStyle, value);            }        }        //[ValueConverter(typeof(TypeValueConverter))]        //public Type TargetType        //{        //    get { return GetPropertyValue<Type>("TargetType"); }        //    set { SetPropertyValue<Type>("TargetType", value); }        //}        public string Name        {            get { return name; }            set            {                SetPropertyValue<string>("Name", ref name, value);                OnPropertyChanged("Name");            }        }        public int Index        {            get { return index; }            set { SetPropertyValue<int>("Index", ref index, value); }        }        public string ImageName        {            get            {                if (string.IsNullOrEmpty(imageName))                {                    return GetEmptyImageName();                }                return imageName;            }            set            {                imageName = value;            }        }        [Browsable(false)]        [Association("NavigationObject-NavigationItems")]        public NavigationObject NavigationObject        {            get { return navigationObject != null ? navigationObject : Parent != null ? Parent.NavigationObject : null; }            set { SetPropertyValue<NavigationObject>("NavigationObject", ref navigationObject, value); }        }        [Browsable(false)]        [Association("NavigationItem-NavigationItems")]        public NavigationItem Parent        {            get { return parent; }            set { SetPropertyValue<NavigationItem>("Parent", ref parent, value); }        }        [Browsable(false)]        [Association("NavigationItem-NavigationItems"), Aggregated]        public XPCollection<NavigationItem> Items        {            get { return GetCollection<NavigationItem>("Items"); }        }        public event PropertyChangedEventHandler PropertyChanged;    }
另外,附上代码中用到的一个枚举类型:

public enum DemoNavigationChildItemsDisplayStyle    {        Default,        LargeIcons,        List    }
4.然后,要实现一个WindowController,该Controller的目地是:点击主导航栏的"Navigation System"显示NavigationObject 的DetailView,代码如下:

/*NavigationDemoWindowController的作用是     * 点击主navigation按钮时显示NavigationObject     * 的DetailView,使用了ShowNavigationItemController     * 的CustomShowNavigationItem事件     */    public partial class NavigationDemoWindowController : WindowController    {        private static ModelApplicationCreator modelCreatorInstance;        private ShowNavigationItemController showNavigationItemController;        private void SubscribeToEvents()        {            showNavigationItemController.CustomShowNavigationItem += new EventHandler<CustomShowNavigationItemEventArgs>(showNavigationItemController_CustomShowNavigationItem);        }        private void UnsubscribeFromEvents()        {            showNavigationItemController.CustomShowNavigationItem -= new EventHandler<CustomShowNavigationItemEventArgs>(showNavigationItemController_CustomShowNavigationItem);        }        private void showNavigationItemController_CustomShowNavigationItem(object sender, CustomShowNavigationItemEventArgs e)        {            ViewShortcut viewShortcut = e.ActionArguments.SelectedChoiceActionItem.Data as ViewShortcut;            string listViewId = Application.FindListViewId(typeof(NavigationObject));            if (viewShortcut != null)            {                //验证是否选中需要的navigation项                if (viewShortcut.ViewId == listViewId)                {                    IObjectSpace objectSpace = Application.CreateObjectSpace();                                        DetailView detailView = Application.CreateDetailView(objectSpace, objectSpace.FindObject(typeof(NavigationObject), null));                    detailView.ViewEditMode = DevExpress.ExpressApp.Editors.ViewEditMode.Edit;                    e.ActionArguments.ShowViewParameters.CreatedView = detailView;                    e.ActionArguments.ShowViewParameters.TargetWindow = TargetWindow.Current;                    e.Handled = true;                }            }        }        protected override void OnFrameAssigned()        {            base.OnFrameAssigned();            ModelCreatorInstance = ((ModelNode)Application.Model).CreatorInstance;            showNavigationItemController = Frame.GetController<ShowNavigationItemController>();            if (showNavigationItemController != null)            {                UnsubscribeFromEvents();                SubscribeToEvents();            }        }        protected override void Dispose(bool disposing)        {            if (showNavigationItemController != null)            {                UnsubscribeFromEvents();                showNavigationItemController = null;            }            base.Dispose(disposing);        }        public NavigationDemoWindowController()        {            TargetWindowType = WindowType.Main;        }        internal static ModelApplicationCreator ModelCreatorInstance        {            get            {                return modelCreatorInstance;            }            set            {                modelCreatorInstance = value;            }        }    }
5.实现一个ViewController,处理一些相应逻辑

public class NavigationObjectDetailViewController : ViewController    {        private NavigationObject CurrentObject        {            get            {                return View.CurrentObject as NavigationObject;            }        }        private void RefreshNavigationActionContainer()        {            PropertyEditor editor = (PropertyEditor)((DetailView)View).FindItem("Action");            editor.Refresh();        }        private void View_ControlsCreated(object sender, EventArgs e)        {            RefreshNavigationActionContainer();            NavigationObject v=View.CurrentObject as NavigationObject;        }        private void SubscribeToEvents()        {            View.ObjectSpace.ObjectChanged += new EventHandler<ObjectChangedEventArgs>(ObjectSpace_ObjectChanged);            View.ControlsCreated += new EventHandler(View_ControlsCreated);        }        private void UnsubscribeFromEvents()        {            View.ObjectSpace.ObjectChanged -= new EventHandler<ObjectChangedEventArgs>(ObjectSpace_ObjectChanged);            View.ControlsCreated -= new EventHandler(View_ControlsCreated);        }        private void ObjectSpace_ObjectChanged(object sender, ObjectChangedEventArgs e)        {            if (!string.IsNullOrEmpty(e.PropertyName))            {                CurrentObject.BuildAction();                RefreshNavigationActionContainer();            }        }        protected override void OnActivated()        {            base.OnActivated();            SubscribeToEvents();            RefreshNavigationActionContainer();        }        protected override void OnDeactivated()        {            ObjectSpace.CommitChanges();            UnsubscribeFromEvents();            base.OnDeactivated();        }        public NavigationObjectDetailViewController()        {            TargetViewType = ViewType.DetailView;            TargetObjectType = typeof(NavigationObject);        }    }
6.最后,在Updater.cs中附加必要的数据

public override void UpdateDatabaseAfterUpdateSchema()        {            base.UpdateDatabaseAfterUpdateSchema();            if (ObjectSpace.FindObject<NavigationObject>(null) == null)            {                NavigationObject NavigationObject = ObjectSpace.CreateObject<NavigationObject>();                NavigationItem linearGroup = CreateLinearNavigationGroup(NavigationObject);                NavigationItem hierarchicalGroup = CreateHierarchicalNavigationGroup(NavigationObject);                NavigationObject.NavigationItems.Add(linearGroup);                NavigationObject.NavigationItems.Add(hierarchicalGroup);                NavigationObject.Save();            }            ObjectSpace.CommitChanges();        }        private NavigationItem CreateLinearNavigationGroup(NavigationObject NavigationObject)        {            NavigationItem group = ObjectSpace.CreateObject<NavigationItem>();            group.Name = "Linear Group";            group.Items.Add(CreateNavigationItem("Contacts", "BO_Contact", 0, NavigationObject));            group.Items.Add(CreateNavigationItem("Tasks", "BO_Task", 1, NavigationObject));            group.Index = 0;            return group;        }        private NavigationItem CreateHierarchicalNavigationGroup(NavigationObject NavigationObject)        {            NavigationItem group = ObjectSpace.CreateObject<NavigationItem>();            group.Name = "Hierarchical Group";            NavigationItem staffItem = CreateNavigationItem("Staff", "BO_Person", 0, NavigationObject);            group.Items.Add(staffItem);            staffItem.Items.Add(CreateNavigationItem("Labour", "BO_Employee", 0, NavigationObject));            staffItem.Items.Add(CreateNavigationItem("Managers", "BO_Position", 1, NavigationObject));            group.Index = 1;            return group;        }        private NavigationItem CreateNavigationItem(string caption, string imageName, int index, NavigationObject NavigationObject)        {            NavigationItem item = ObjectSpace.CreateObject<NavigationItem>();            item.Name = caption;            item.ImageName = imageName;            item.Index = index;            NavigationObject.NavigationItems.Add(item);            return item;        }