这章主要说插件的菜单,可以说菜单是最核心的部分,前面我们已经实现了Document添加,现在主要就是生成具有层级关系的菜单,以及把菜单跟我们自定义的Document关联起来,也就是MenuPart->View->Model的关联,菜单的实现部分我也是网上参照别人的来实现的,由于代码比较多,我就抽一些重要的来说,其他的只能靠各位自己去体会了,不明白的可以照葫芦画瓢,这菜单部分可以直接抽出来用的,我们不需要明白它内部是怎么实现的,能用就行了,其实有些地方我也没有深入去了解,我们主要的任务是把现有的技术融合成一个可用的插件平台,技术的细节以后有时间再讨论。。。

  额外提示所有关于UI的操作都是以绑定的方式实现的,如果不熟悉WPF以及MVVM模式可能会难以理解    [BY Zengg]

运行结果:

AvalonDock 2.0+Caliburn.Micro+MahApps.Metro实现Metro风格插件式系统(菜单篇)

  可以看到我们已经能做到通过菜单来控制插件的显示以及关闭,插件平台已经初具雏形

UICore部分

涉及到核心的项目结构部分:

AvalonDock 2.0+Caliburn.Micro+MahApps.Metro实现Metro风格插件式系统(菜单篇)

IPart 定义了菜单的基本属性,主要的方法是 void Execute(),这是单击菜单后的执行方法, 之后我们得把Show出Document的动作写入Execute方法里面。

 1 namespace UICoreFramework
 2 {
 3     /// <summary>
 4     /// Denotes an instance which can be executed.
 5     /// </summary>
 6     public interface IExecutable
 7     {
 8         bool CanExecute { get; }
 9         void Execute();
10     }
11 
12     /// <summary>
13     /// Denotes an instance which can be checked.
14     /// </summary>
15     public interface ICheckable
16     {
17         bool IsCheckable { get; }
18         bool IsChecked { get; set; }
19     }
20 
21     /// <summary>
22     /// Denotes a small UI widget that can display and interact.
23     /// </summary>
24     public interface IPart : ILocalizableDisplay, IExecutable, IActivate, IDeactivate
25     {
26         string InputGestureText { get; set; }
27 
28         void OnAttached();
29         
30         string Icon { get; set; }
31 
32         bool IsVisible { get; set; }
33     }
34 
35     /// <summary>
36     /// Concrete <see cref="IPart"/> which denotes a <see cref="System.Window.Controls.MenuItem"/> instance.
37     /// </summary>
38     public interface IMenuPart : IPart, ISeparaterPart, ICheckable
39     {
40 
41     }
42 
43     /// <summary>
44     /// Denotes a <see cref="System.Window.Controls.Separater"/> instance.
45     /// </summary>
46     public interface ISeparaterPart
47     {
48         bool IsSeparator { get; }
49     }
50 
51     /// <summary>
52     /// Denotes a manager class that manage the <see cref="IPart"/>s.
53     /// </summary>
54     public interface IPartManager<T> where T : IPart
55     {
56         IObservableCollection<T> Items { get; }
57     }
58 
59     /// <summary>
60     /// Denotes a manager node that holds the <see cref="IObservableCollection"/> item.
61     /// </summary>
62     public interface IObservableParent<T>
63     {
64         IObservableCollection<T> Items { get; }
65     }
66 }

 

PartBase IPart的抽象类主要实现了IPart接口以及一些共同的抽象函数。

namespace UICoreFramework
{
    /// <summary>
    /// Base <see cref="IPart"/> class for various implementations of <see cref="IPart"/>.
    /// </summary>
    public abstract class PartBase : PropertyChangedBase, IPart
    {
        protected PartBase()
            :this(null)
        {
        }

        protected PartBase(string name)
        {
            DisplayName = name;
            this.Name = name ?? GetType().Name.Replace("Part", string.Empty);
            this.execute = ((i) => { });
            this.canExecute = (() => IsActive);
        }

        public PartBase(string name, System.Action<PartBase> execute, Func<bool> canExecute = null)
            : this(name)
        {
            this.execute = execute ?? ((i) => { });
            this.canExecute = canExecute ?? (() => IsActive);
        }

        private string name;
        public string Name
        {
            get { return name; }
            protected set { name = value; NotifyOfPropertyChange(() => Name); }
        }

        private string displayName;
        public string DisplayName
        {
            get { return displayName; }
            set { displayName = value; NotifyOfPropertyChange(() => DisplayName); }
        }

        private string icon;
        public string Icon
        {
            get { return icon; }
            set { icon = value; NotifyOfPropertyChange(() => Icon); }
        }

        private string inputGestureText;
        public string InputGestureText
        {
            get { return inputGestureText; }
            set { inputGestureText = value; NotifyOfPropertyChange(() => InputGestureText); }
        }

        private bool isVisible = true;
        public bool IsVisible
        {
            get { return isVisible; }
            set { isVisible = value; NotifyOfPropertyChange(() => IsVisible); }
        }

        public virtual void OnAttached()
        { }

        #region IExecutable

        private readonly System.Action<PartBase> execute;
        /// <summary>
        /// The action associated to the ActionItem
        /// </summary>
        public virtual void Execute()
        {
            this.execute(this);
        }

        private readonly Func<bool> canExecute;
        /// <summary>
        /// Calls the underlying canExecute function.
        /// </summary>
        public virtual bool CanExecute
        {
            get { return canExecute(); }
        }
        #endregion

        #region Activation & Deactivation
        public event EventHandler<ActivationEventArgs> Activated;
        public event EventHandler<DeactivationEventArgs> AttemptingDeactivation;
        public event EventHandler<DeactivationEventArgs> Deactivated;

        private bool isActive = true;
        public bool IsActive
        {
            get { return isActive; }
        }

        public void Activate()
        {
            if (IsActive)
                return;

            isActive = true;
            OnActivate();
            if (Activated != null)
                Activated(this, new ActivationEventArgs { WasInitialized = false });
            NotifyOfPropertyChange(() => CanExecute);
        }
        protected virtual void OnActivate() { }

        public virtual void Deactivate(bool close)
        {
            if (!IsActive)
                return;

            if (AttemptingDeactivation != null)
                AttemptingDeactivation(this, new DeactivationEventArgs { WasClosed = close });

            isActive = false;
            OnDeactivate(close);
            NotifyOfPropertyChange(() => CanExecute);
            if (Deactivated != null)
                Deactivated(this, new DeactivationEventArgs { WasClosed = close });
        }
        protected virtual void OnDeactivate(bool close) { }

        #endregion

        #region IHandle<LanguageChangedEventArgs> Members

        //public void Handle(LanguageChangedMessage message)
        //{
        //    this.UpdateDisplayName();
        //}

        #endregion

    }
}
PartBase

相关文章: