开发者论坛

 找回密码
 注册 (请使用非IE浏览器)
查看: 7421|回复: 8

XAF之实现子导航栏 (转)

[复制链接]

0

精华

161

贡献

57

赞扬

帖子
112
软币
1615
在线时间
263 小时
注册时间
2013-6-14
发表于 2013-6-19 19:06:53 | 显示全部楼层 |阅读模式
本帖最后由 linuxsc 于 2013-6-19 19:06 编辑

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


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

1. 首先,定义两个Business类,一个NavigationObject代表图中主显示区的对象,注意包含了一个SingleChoiceAction和子项的集合。
  1.     public  class NavigationObject : BaseObject, INotifyPropertyChanged
  2.     {
  3.         private ItemsDisplayStyle defaultChildItemsDisplayStyle = ItemsDisplayStyle.List;
  4.         private NavigationStyle navigationStyle = NavigationStyle.NavBar;
  5.         private SingleChoiceAction action;
  6.         private bool isWebApplication;
  7.         private void action_Execute(object sender, SingleChoiceActionExecuteEventArgs e)
  8.         {
  9.             Console.WriteLine(string.Format("The '{0}' navigation item is selected", e.SelectedChoiceActionItem.Caption));
  10.         }
  11.         private void ProcessItem(NavigationItem item, ChoiceActionItemCollection choiceActionItemCollection, ModelNode parentModel)
  12.         {
  13.             object objectKey = Session.GetKeyValue(item);
  14.             IModelNavigationItem modelNavigaionItem = parentModel.AddNode<IModelNavigationItem>(objectKey.ToString());
  15.             FillNavigationItemModel(item, modelNavigaionItem);
  16.             ChoiceActionItem choiceActionItem = new ChoiceActionItem(modelNavigaionItem, item);
  17.             choiceActionItem.ImageName = item.ImageName;
  18.             choiceActionItemCollection.Add(choiceActionItem);
  19.             SortItems(item.Items);
  20.             foreach (NavigationItem childItem in item.Items)
  21.             {
  22.                 ProcessItem(childItem, choiceActionItem.Items, (ModelNode)modelNavigaionItem);
  23.             }
  24.         }
  25.         private void FillNavigationItemModel(NavigationItem item, IModelNavigationItem modelNavigaionItem)
  26.         {
  27.             modelNavigaionItem.Caption = item.Name;
  28.             modelNavigaionItem.Index = item.Index;
  29.             if (item.ChildItemsDisplayStyle == DemoNavigationChildItemsDisplayStyle.Default)
  30.             {
  31.                 modelNavigaionItem.ChildItemsDisplayStyle = item.NavigationObject.DefaultChildItemsDisplayStyle;
  32.             }
  33.             else
  34.             {
  35.                 modelNavigaionItem.ChildItemsDisplayStyle = item.ChildItemsDisplayStyle == DemoNavigationChildItemsDisplayStyle.List ? ItemsDisplayStyle.List : ItemsDisplayStyle.LargeIcons;
  36.             }
  37.             modelNavigaionItem.ImageName = item.ImageName;
  38.         }
  39.         protected virtual void OnPropertyChanged(string propertyName)
  40.         {
  41.             if (PropertyChanged != null)
  42.             {
  43.                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  44.             }
  45.         }
  46.         protected override void OnLoaded()
  47.         {
  48.             base.OnLoaded();
  49.             BuildAction();
  50.         }
  51.         internal void BuildAction()
  52.         {
  53.             //B152525
  54.             Action.Items.Clear();
  55.             SortItems(NavigationItems);
  56.             ModelApplicationCreator creator = NavigationDemoWindowController.ModelCreatorInstance;
  57.             if (creator != null)
  58.             {
  59.                 ModelNode modelNavigationItems = creator.CreateNode(Guid.NewGuid().ToString(), typeof(IModelNavigationItems));
  60.                 foreach (NavigationItem item in NavigationItems)
  61.                 {
  62.                     if (item.Parent == null)
  63.                     {
  64.                         ProcessItem(item, Action.Items, modelNavigationItems);
  65.                     }
  66.                 }
  67.             }
  68.         }
  69.         private void SortItems(XPCollection<NavigationItem> items)
  70.         {
  71.             items.Sorting.Clear();
  72.             items.Sorting.Add(new SortProperty("Index", DevExpress.Xpo.DB.SortingDirection.Ascending));
  73.         }
  74.         public NavigationObject(Session session)
  75.             : base(session)
  76.         {
  77.             action = new SingleChoiceAction();
  78.             action.Caption = "Navigation";
  79.             action.Execute += new SingleChoiceActionExecuteEventHandler(action_Execute);
  80.         }
  81.         [Browsable(false), NonPersistent]
  82.         public bool IsWebApplication
  83.         {
  84.             get { return isWebApplication; }
  85.             set
  86.             {
  87.                 isWebApplication = value;
  88.             }
  89.         }
  90.         [ImmediatePostData]
  91.         public ItemsDisplayStyle DefaultChildItemsDisplayStyle
  92.         {
  93.             get { return defaultChildItemsDisplayStyle; }
  94.             set
  95.             {
  96.                 SetPropertyValue<ItemsDisplayStyle>("DefaultChildItemsDisplayStyle", ref defaultChildItemsDisplayStyle, value);
  97.                 //OnPropertyChanged("Hint");
  98.             }
  99.         }
  100.         [ImmediatePostData]
  101.         public NavigationStyle NavigationStyle
  102.         {
  103.             get { return navigationStyle; }
  104.             set
  105.             {
  106.                 SetPropertyValue<NavigationStyle>("NavigationStyle", ref navigationStyle, value);
  107.             }
  108.         }
  109.         //子导航的根节点
  110.         public SingleChoiceAction Action
  111.         {
  112.             get { return action; }
  113.         }
  114.         //子项的集合
  115.         [Association("NavigationObject-NavigationItems"), Aggregated]
  116.         public XPCollection<NavigationItem> NavigationItems
  117.         {
  118.             get { return GetCollection<NavigationItem>("NavigationItems"); }
  119.         }
  120.         public event PropertyChangedEventHandler PropertyChanged;
  121.    }
复制代码
2.为其SingleChoiceAction属性实现PropertyEditor
  1.     [PropertyEditor(typeof(SingleChoiceAction))]
  2.     public class NavigationActionContainerPropertyEditor : PropertyEditor
  3.     {
  4.         private NavigationActionContainer NavigationActionContainer
  5.         {
  6.             get { return (NavigationActionContainer)Control; }
  7.         }
  8.         private NavigationObject NavigationObject
  9.         {
  10.             get
  11.             {
  12.                 return (NavigationObject)CurrentObject;
  13.             }
  14.         }
  15.         protected override object CreateControlCore()
  16.         {
  17.             return new NavigationActionContainer();
  18.         }
  19.         protected override void ReadValueCore()
  20.         {
  21.             NavigationActionContainer.Register((SingleChoiceAction)PropertyValue, NavigationObject.NavigationStyle);
  22.         }
  23.         protected override object GetControlValueCore()
  24.         {
  25.             return null;
  26.         }
  27.         public NavigationActionContainerPropertyEditor(Type objectType, IModelMemberViewItem info) : base(objectType, info) { }
  28.     }
复制代码
3.实现要显示的子项类NavigationItem,其中Index属性是做排序和图标选择用途,该类没有特别的含义,只为了显示结果
  1.     public class NavigationItem : BaseObject, INotifyPropertyChanged
  2.     {
  3.         private string name;
  4.         private int index;
  5.         private DemoNavigationChildItemsDisplayStyle childItemsDisplayStyle;
  6.         private NavigationItem parent;
  7.         private NavigationObject navigationObject;
  8.         private string imageName;
  9.         private string GetEmptyImageName()
  10.         {
  11.             return Items.Count == 0 ? "BO_Unknown" : "BO_Folder";
  12.         }
  13.         protected virtual void OnPropertyChanged(string propertyName)
  14.         {
  15.             if (PropertyChanged != null)
  16.             {
  17.                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  18.             }
  19.         }
  20.         public NavigationItem(Session session) : base(session) { }
  21.         [ImmediatePostData]
  22.         public DemoNavigationChildItemsDisplayStyle ChildItemsDisplayStyle
  23.         {
  24.             get { return childItemsDisplayStyle; }
  25.             set
  26.             {
  27.                 SetPropertyValue<DemoNavigationChildItemsDisplayStyle>("ChildItemsDisplayStyle", ref childItemsDisplayStyle, value);
  28.             }
  29.         }
  30.         //[ValueConverter(typeof(TypeValueConverter))]
  31.         //public Type TargetType
  32.         //{
  33.         //    get { return GetPropertyValue<Type>("TargetType"); }
  34.         //    set { SetPropertyValue<Type>("TargetType", value); }
  35.         //}
  36.         public string Name
  37.         {
  38.             get { return name; }
  39.             set
  40.             {
  41.                 SetPropertyValue<string>("Name", ref name, value);
  42.                 OnPropertyChanged("Name");
  43.             }
  44.         }
  45.         public int Index
  46.         {
  47.             get { return index; }
  48.             set { SetPropertyValue<int>("Index", ref index, value); }
  49.         }
  50.         public string ImageName
  51.         {
  52.             get
  53.             {
  54.                 if (string.IsNullOrEmpty(imageName))
  55.                 {
  56.                     return GetEmptyImageName();
  57.                 }
  58.                 return imageName;
  59.             }
  60.             set
  61.             {
  62.                 imageName = value;
  63.             }
  64.         }
  65.         [Browsable(false)]
  66.         [Association("NavigationObject-NavigationItems")]
  67.         public NavigationObject NavigationObject
  68.         {
  69.             get { return navigationObject != null ? navigationObject : Parent != null ? Parent.NavigationObject : null; }
  70.             set { SetPropertyValue<NavigationObject>("NavigationObject", ref navigationObject, value); }
  71.         }
  72.         [Browsable(false)]
  73.         [Association("NavigationItem-NavigationItems")]
  74.         public NavigationItem Parent
  75.         {
  76.             get { return parent; }
  77.             set { SetPropertyValue<NavigationItem>("Parent", ref parent, value); }
  78.         }
  79.         [Browsable(false)]
  80.         [Association("NavigationItem-NavigationItems"), Aggregated]
  81.         public XPCollection<NavigationItem> Items
  82.         {
  83.             get { return GetCollection<NavigationItem>("Items"); }
  84.         }
  85.         public event PropertyChangedEventHandler PropertyChanged;
  86.     }
复制代码
另外,附上代码中用到的一个枚举类型:
  1.    public enum DemoNavigationChildItemsDisplayStyle
  2.     {
  3.         Default,
  4.         LargeIcons,
  5.         List
  6.     }
复制代码
4.然后,要实现一个WindowController,该Controller的目地是:点击主导航栏的"Navigation System"显示NavigationObject 的DetailView,代码如下:
  1. /*NavigationDemoWindowController的作用是
  2.      * 点击主navigation按钮时显示NavigationObject
  3.      * 的DetailView,使用了ShowNavigationItemController
  4.      * 的CustomShowNavigationItem事件
  5.      */
  6.     public partial class NavigationDemoWindowController : WindowController
  7.     {
  8.         private static ModelApplicationCreator modelCreatorInstance;
  9.         private ShowNavigationItemController showNavigationItemController;
  10.         private void SubscribeToEvents()
  11.         {
  12.             showNavigationItemController.CustomShowNavigationItem += new EventHandler<CustomShowNavigationItemEventArgs>(showNavigationItemController_CustomShowNavigationItem);
  13.         }
  14.         private void UnsubscribeFromEvents()
  15.         {
  16.             showNavigationItemController.CustomShowNavigationItem -= new EventHandler<CustomShowNavigationItemEventArgs>  (showNavigationItemController_CustomShowNavigationItem);
  17.         }
  18.         private void showNavigationItemController_CustomShowNavigationItem(object sender, CustomShowNavigationItemEventArgs e)
  19.         {
  20.             ViewShortcut viewShortcut = e.ActionArguments.SelectedChoiceActionItem.Data as ViewShortcut;
  21.             string listViewId = Application.FindListViewId(typeof(NavigationObject));
  22.             if (viewShortcut != null)
  23.             {
  24.                 //验证是否选中需要的navigation项
  25.                 if (viewShortcut.ViewId == listViewId)
  26.                 {
  27.                     IObjectSpace objectSpace = Application.CreateObjectSpace();
  28.                     
  29.                     DetailView detailView = Application.CreateDetailView(objectSpace, objectSpace.FindObject(typeof(NavigationObject), null));
  30.                     detailView.ViewEditMode = DevExpress.ExpressApp.Editors.ViewEditMode.Edit;
  31.                     e.ActionArguments.ShowViewParameters.CreatedView = detailView;
  32.                     e.ActionArguments.ShowViewParameters.TargetWindow = TargetWindow.Current;
  33.                     e.Handled = true;
  34.                 }
  35.             }
  36.         }
  37.         protected override void OnFrameAssigned()
  38.         {
  39.             base.OnFrameAssigned();
  40.             ModelCreatorInstance = ((ModelNode)Application.Model).CreatorInstance;
  41.             showNavigationItemController = Frame.GetController<ShowNavigationItemController>();
  42.             if (showNavigationItemController != null)
  43.             {
  44.                 UnsubscribeFromEvents();
  45.                 SubscribeToEvents();
  46.             }
  47.         }
  48.         protected override void Dispose(bool disposing)
  49.         {
  50.             if (showNavigationItemController != null)
  51.             {
  52.                 UnsubscribeFromEvents();
  53.                 showNavigationItemController = null;
  54.             }
  55.             base.Dispose(disposing);
  56.         }
  57.         public NavigationDemoWindowController()
  58.         {
  59.             TargetWindowType = WindowType.Main;
  60.         }
  61.         internal static ModelApplicationCreator ModelCreatorInstance
  62.         {
  63.             get
  64.             {
  65.                 return modelCreatorInstance;
  66.             }
  67.             set
  68.             {
  69.                 modelCreatorInstance = value;
  70.             }
  71.         }
  72.     }
复制代码
5.实现一个ViewController,处理一些相应逻辑
  1.     public class NavigationObjectDetailViewController : ViewController
  2.     {
  3.         private NavigationObject CurrentObject
  4.         {
  5.             get
  6.             {
  7.                 return View.CurrentObject as NavigationObject;
  8.             }
  9.         }
  10.         private void RefreshNavigationActionContainer()
  11.         {
  12.             PropertyEditor editor = (PropertyEditor)((DetailView)View).FindItem("Action");
  13.             editor.Refresh();
  14.         }
  15.         private void View_ControlsCreated(object sender, EventArgs e)
  16.         {
  17.             RefreshNavigationActionContainer();
  18.             NavigationObject v=View.CurrentObject as NavigationObject;
  19.         }
  20.         private void SubscribeToEvents()
  21.         {
  22.             View.ObjectSpace.ObjectChanged += new EventHandler<ObjectChangedEventArgs>(ObjectSpace_ObjectChanged);
  23.             View.ControlsCreated += new EventHandler(View_ControlsCreated);
  24.         }
  25.         private void UnsubscribeFromEvents()
  26.         {
  27.             View.ObjectSpace.ObjectChanged -= new EventHandler<ObjectChangedEventArgs>(ObjectSpace_ObjectChanged);
  28.             View.ControlsCreated -= new EventHandler(View_ControlsCreated);
  29.         }
  30.         private void ObjectSpace_ObjectChanged(object sender, ObjectChangedEventArgs e)
  31.         {
  32.             if (!string.IsNullOrEmpty(e.PropertyName))
  33.             {
  34.                 CurrentObject.BuildAction();
  35.                 RefreshNavigationActionContainer();
  36.             }
  37.         }
  38.         protected override void OnActivated()
  39.         {
  40.             base.OnActivated();
  41.             SubscribeToEvents();
  42.             RefreshNavigationActionContainer();
  43.         }
  44.         protected override void OnDeactivated()
  45.         {
  46.             ObjectSpace.CommitChanges();
  47.             UnsubscribeFromEvents();
  48.             base.OnDeactivated();
  49.         }
  50.         public NavigationObjectDetailViewController()
  51.         {
  52.             TargetViewType = ViewType.DetailView;
  53.             TargetObjectType = typeof(NavigationObject);
  54.         }
  55.     }
复制代码
6.最后,在Updater.cs中附加必要的数据
  1. public override void UpdateDatabaseAfterUpdateSchema()
  2.         {
  3.             base.UpdateDatabaseAfterUpdateSchema();
  4.             if (ObjectSpace.FindObject<NavigationObject>(null) == null)
  5.             {
  6.                 NavigationObject NavigationObject = ObjectSpace.CreateObject<NavigationObject>();
  7.                 NavigationItem linearGroup = CreateLinearNavigationGroup(NavigationObject);
  8.                 NavigationItem hierarchicalGroup = CreateHierarchicalNavigationGroup(NavigationObject);
  9.                 NavigationObject.NavigationItems.Add(linearGroup);
  10.                 NavigationObject.NavigationItems.Add(hierarchicalGroup);
  11.                 NavigationObject.Save();
  12.             }
  13.             ObjectSpace.CommitChanges();
  14.         }
  15.         private NavigationItem CreateLinearNavigationGroup(NavigationObject NavigationObject)
  16.         {
  17.             NavigationItem group = ObjectSpace.CreateObject<NavigationItem>();
  18.             group.Name = "Linear Group";
  19.             group.Items.Add(CreateNavigationItem("Contacts", "BO_Contact", 0, NavigationObject));
  20.             group.Items.Add(CreateNavigationItem("Tasks", "BO_Task", 1, NavigationObject));
  21.             group.Index = 0;
  22.             return group;
  23.         }
  24.         private NavigationItem CreateHierarchicalNavigationGroup(NavigationObject NavigationObject)
  25.         {
  26.             NavigationItem group = ObjectSpace.CreateObject<NavigationItem>();
  27.             group.Name = "Hierarchical Group";
  28.             NavigationItem staffItem = CreateNavigationItem("Staff", "BO_Person", 0, NavigationObject);
  29.             group.Items.Add(staffItem);
  30.             staffItem.Items.Add(CreateNavigationItem("Labour", "BO_Employee", 0, NavigationObject));
  31.             staffItem.Items.Add(CreateNavigationItem("Managers", "BO_Position", 1, NavigationObject));
  32.             group.Index = 1;
  33.             return group;
  34.         }
  35.         private NavigationItem CreateNavigationItem(string caption, string imageName, int index, NavigationObject NavigationObject)
  36.         {
  37.             NavigationItem item = ObjectSpace.CreateObject<NavigationItem>();
  38.             item.Name = caption;
  39.             item.ImageName = imageName;
  40.             item.Index = index;
  41.             NavigationObject.NavigationItems.Add(item);
  42.             return item;
  43.         }
复制代码

评分

参与人数 8贡献 +4 赞扬 +7 收起 理由
maple + 1 感谢分享
razer + 1 感谢分享
huashan + 1 很给力
jiongge + 1 Thanks
cosky + 1 Thanks

查看全部评分

回复

使用道具 举报

0

精华

940

贡献

167

赞扬

正版授权组

Rank: 14Rank: 14Rank: 14Rank: 14

帖子
237
软币
2692
在线时间
264 小时
注册时间
2013-6-17
发表于 2013-6-20 04:30:34 | 显示全部楼层
虽然不会用XAF,但是可以先收藏,谢谢
回复

使用道具 举报

0

精华

2

贡献

19

赞扬

帖子
15
软币
1114
在线时间
11 小时
注册时间
2013-6-8
发表于 2013-6-20 07:52:01 | 显示全部楼层
最好能做一个DEMO,不然调试麻烦。
回复

使用道具 举报

0

精华

480

贡献

696

赞扬

DX汉化组

帖子
282
软币
6775
在线时间
1170 小时
注册时间
2013-6-8
发表于 2013-6-22 08:22:07 | 显示全部楼层
楼主,把解决方案源码发出来,你的代码有几处无法编译
回复

使用道具 举报

0

精华

0

贡献

0

赞扬

帖子
2
软币
32
在线时间
1 小时
注册时间
2013-7-9
发表于 2013-7-9 13:46:48 | 显示全部楼层
polite0803 发表于 2013-6-22 08:22
楼主,把解决方案源码发出来,你的代码有几处无法编译

1
回复

使用道具 举报

0

精华

0

贡献

2

赞扬

帖子
29
软币
350
在线时间
42 小时
注册时间
2013-7-29
发表于 2013-10-28 16:27:26 | 显示全部楼层
解决了我头疼的问题了!
回复

使用道具 举报

0

精华

518

贡献

366

赞扬

正版授权组

Rank: 14Rank: 14Rank: 14Rank: 14

帖子
213
软币
7151
在线时间
1174 小时
注册时间
2013-6-9
发表于 2013-11-4 17:15:27 | 显示全部楼层
耶解决了我的问题
回复

使用道具 举报

0

精华

0

贡献

15

赞扬

帖子
34
软币
1215
在线时间
28 小时
注册时间
2013-6-9
发表于 2013-12-18 15:34:43 | 显示全部楼层
这个AXF帮助文档中的内容,帮助里有完整项目的链接。
回复

使用道具 举报

0

精华

5

贡献

13

赞扬

帖子
113
软币
647
在线时间
71 小时
注册时间
2013-8-12
发表于 2014-4-2 19:44:38 | 显示全部楼层
好贴. 搜藏之
回复

使用道具 举报

Archiver|手机版|小黑屋|开发者网 ( 苏ICP备08004430号-2 )
版权所有:南京韵文教育信息咨询有限公司

GMT+8, 2024-6-1 23:38

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表