当前位置:网站首页 / WPF / 正文

AY 基于AvalonDock写个ide行为[1/10]

时间:2019年06月06日 | 作者 : aaronyang | 分类 : WPF | 浏览: 940次 | 评论 0

(文件不适合初级wpf学习者看,至少看完了wpf编程宝典2遍以上,并且具有命令开发方式的人阅读,我不考虑初级阅读者了。)

自己建wpf项目,nuget引用安装

image.png

以前我写的一篇avalonDock文章 没啥意思,现在又有时间折腾了,以下内容自己做个笔记

====================www.ayjs.net       杨洋    wpfui.com        ayui      ay  aaronyang=======请不要转载谢谢了。=========

总结结构:

DockingManager 

LayoutRoot 

LayoutPanel 

后面的LayoutDocumentPaneGroup可以理解为分组 

接着开始就是填内容,有两类 

LayoutAnchorablePane,这控件是可以再放到全局任意一个地方 

LayoutDocumentPane ,这控件主要是文档内容,一般取中间,反正就是需要足够的位置给它。 

重要功能 布局的保存,把布局写到文件,然后在恢复布局。


源码代码量庞大,大致知道就好,


这个库,每一次上一个版本的代码都是开源的,目前开源的是3.4,在github的wpftoolkit里 最新的是3.8

我们直接nuget安装3.8的avalondock和它的theme



准备工作

接下来,我下载了MVVMLight的源码

https://github.com/lbugnion/mvvmlight

拷贝了,去掉Messaging那块

image.png

拷贝到自己的项目,这样一个基本的MVVM小东西就好了

image.png

需要修改ViewModelBase的代码,去掉消息那块

// ****************************************************************************
// <copyright file="ViewModelBase.cs" company="GalaSoft Laurent Bugnion">
// Copyright © GalaSoft Laurent Bugnion 2009-2016
// </copyright>
// ****************************************************************************
// <author>Laurent Bugnion</author>
// <email>laurent@galasoft.ch</email>
// <date>22.4.2009</date>
// <project>GalaSoft.MvvmLight</project>
// <web>http://www.mvvmlight.net</web>
// <license>
// See license.txt in this project or http://www.galasoft.ch/license_MIT.txt
// </license>
// <LastBaseLevel>BL0014</LastBaseLevel>
// ****************************************************************************

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;

// ReSharper disable RedundantUsingDirective
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using GalaSoft.MvvmLight.Helpers;
// ReSharper restore RedundantUsingDirective

#if NETFX_CORE
#if !PORTABLE
using Windows.ApplicationModel;
#endif
#else
// ReSharper disable RedundantUsingDirective
using System.Windows;
// ReSharper restore RedundantUsingDirective
#endif

////using GalaSoft.Utilities.Attributes;

namespace GalaSoft.MvvmLight
{
    /// <summary>
    /// A base class for the ViewModel classes in the MVVM pattern.
    /// </summary>
    //// [ClassInfo(typeof(ViewModelBase),
    ////  VersionString = "5.3.18",
    ////  DateString = "201604212130",
    ////  Description = "A base class for the ViewModel classes in the MVVM pattern.",
    ////  UrlContacts = "http://www.galasoft.ch/contact_en.html",
    ////  Email = "laurent@galasoft.ch")]
    [SuppressMessage(
        "Microsoft.Design",
        "CA1012",
        Justification = "Constructors should remain public to allow serialization.")]
    public abstract class ViewModelBase : ObservableObject, ICleanup
    {
        //private IMessenger _messengerInstance;
        public ViewModelBase()
        {
        }
        /// <summary>
        /// Initializes a new instance of the ViewModelBase class.
        /// </summary>
        // ReSharper disable PublicConstructorInAbstractClass
        // Must be public to allow for serialization.
        //public ViewModelBase()
        //// ReSharper restore PublicConstructorInAbstractClass
        //    : this(null)
        //{
        //}

        /// <summary>
        /// Initializes a new instance of the ViewModelBase class.
        /// </summary>
        /// <param name="messenger">An instance of a <see cref="Messenger" />
        /// used to broadcast messages to other objects. If null, this class
        /// will attempt to broadcast using the Messenger's default
        /// instance.</param>
        // ReSharper disable PublicConstructorInAbstractClass
        //public ViewModelBase(IMessenger messenger)
        //// ReSharper restore PublicConstructorInAbstractClass
        //{
        //    MessengerInstance = messenger;
        //}

        /// <summary>
        /// Gets a value indicating whether the control is in design mode
        /// (running under Blend or Visual Studio).
        /// </summary>
        [SuppressMessage(
            "Microsoft.Performance",
            "CA1822:MarkMembersAsStatic",
            Justification = "Non static member needed for data binding")]
        public bool IsInDesignMode
        {
            get
            {
                return IsInDesignModeStatic;
            }
        }

        /// <summary>
        /// Gets a value indicating whether the control is in design mode
        /// (running in Blend or Visual Studio).
        /// </summary>
        [SuppressMessage(
            "Microsoft.Security",
            "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands",
            Justification = "The security risk here is neglectible.")]
        public static bool IsInDesignModeStatic
        {
            get
            {
                return DesignerLibrary.IsInDesignMode;
            }
        }

        /// <summary>
        /// Gets or sets an instance of a <see cref="IMessenger" /> used to
        /// broadcast messages to other objects. If null, this class will
        /// attempt to broadcast using the Messenger's default instance.
        /// </summary>
        //protected IMessenger MessengerInstance
        //{
        //    get
        //    {
        //        return _messengerInstance ?? Messenger.Default;
        //    }
        //    set
        //    {
        //        _messengerInstance = value;
        //    }
        //}

        /// <summary>
        /// Unregisters this instance from the Messenger class.
        /// <para>To cleanup additional resources, override this method, clean
        /// up and then call base.Cleanup().</para>
        /// </summary>
        public virtual void Cleanup()
        {
            //MessengerInstance.Unregister(this);
        }

        /// <summary>
        /// Broadcasts a PropertyChangedMessage using either the instance of
        /// the Messenger that was passed to this class (if available) 
        /// or the Messenger's default instance.
        /// </summary>
        /// <typeparam name="T">The type of the property that
        /// changed.</typeparam>
        /// <param name="oldValue">The value of the property before it
        /// changed.</param>
        /// <param name="newValue">The value of the property after it
        /// changed.</param>
        /// <param name="propertyName">The name of the property that
        /// changed.</param>
        //protected virtual void Broadcast<T>(T oldValue, T newValue, string propertyName)
        //{
        //    var message = new PropertyChangedMessage<T>(this, oldValue, newValue, propertyName);
        //    MessengerInstance.Send(message);
        //}

        /// <summary>
        /// Raises the PropertyChanged event if needed, and broadcasts a
        /// PropertyChangedMessage using the Messenger instance (or the
        /// static default instance if no Messenger instance is available).
        /// </summary>
        /// <typeparam name="T">The type of the property that
        /// changed.</typeparam>
        /// <param name="propertyName">The name of the property that
        /// changed.</param>
        /// <param name="oldValue">The property's value before the change
        /// occurred.</param>
        /// <param name="newValue">The property's value after the change
        /// occurred.</param>
        /// <param name="broadcast">If true, a PropertyChangedMessage will
        /// be broadcasted. If false, only the event will be raised.</param>
        /// <remarks>If the propertyName parameter
        /// does not correspond to an existing property on the current class, an
        /// exception is thrown in DEBUG configuration only.</remarks>
        [SuppressMessage(
            "Microsoft.Design", 
            "CA1026:DefaultParametersShouldNotBeUsed"), 
        SuppressMessage(
            "Microsoft.Design", "CA1030:UseEventsWhereAppropriate",
            Justification = "This cannot be an event")]
        public virtual void RaisePropertyChanged<T>(
#if CMNATTR
            [CallerMemberName] string propertyName = null, 
#else
            string propertyName,
#endif
            T oldValue = default(T), 
            T newValue = default(T), 
            bool broadcast = false)
        {
            if (string.IsNullOrEmpty(propertyName))
            {
                throw new ArgumentException("This method cannot be called with an empty string", "propertyName");
            }

            // ReSharper disable ExplicitCallerInfoArgument
            RaisePropertyChanged(propertyName);
            // ReSharper restore ExplicitCallerInfoArgument

            //if (broadcast)
            //{
            //    Broadcast(oldValue, newValue, propertyName);
            //}
        }

        /// <summary>
        /// Raises the PropertyChanged event if needed, and broadcasts a
        /// PropertyChangedMessage using the Messenger instance (or the
        /// static default instance if no Messenger instance is available).
        /// </summary>
        /// <typeparam name="T">The type of the property that
        /// changed.</typeparam>
        /// <param name="propertyExpression">An expression identifying the property
        /// that changed.</param>
        /// <param name="oldValue">The property's value before the change
        /// occurred.</param>
        /// <param name="newValue">The property's value after the change
        /// occurred.</param>
        /// <param name="broadcast">If true, a PropertyChangedMessage will
        /// be broadcasted. If false, only the event will be raised.</param>
        [SuppressMessage(
            "Microsoft.Design", 
            "CA1030:UseEventsWhereAppropriate",
            Justification = "This cannot be an event")]
        [SuppressMessage(
            "Microsoft.Design",
            "CA1006:GenericMethodsShouldProvideTypeParameter",
            Justification = "This syntax is more convenient than the alternatives.")]
        public virtual void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression, T oldValue, T newValue, bool broadcast)
        {
            RaisePropertyChanged(propertyExpression);

            //if (broadcast)
            //{
            //    // Unfortunately I don't see a reliable way to not call GetPropertyName twice.
            //    var propertyName = GetPropertyName(propertyExpression);
            //    Broadcast(oldValue, newValue, propertyName);
            //}
        }

        /// <summary>
        /// Assigns a new value to the property. Then, raises the
        /// PropertyChanged event if needed, and broadcasts a
        /// PropertyChangedMessage using the Messenger instance (or the
        /// static default instance if no Messenger instance is available). 
        /// </summary>
        /// <typeparam name="T">The type of the property that
        /// changed.</typeparam>
        /// <param name="propertyExpression">An expression identifying the property
        /// that changed.</param>
        /// <param name="field">The field storing the property's value.</param>
        /// <param name="newValue">The property's value after the change
        /// occurred.</param>
        /// <param name="broadcast">If true, a PropertyChangedMessage will
        /// be broadcasted. If false, only the event will be raised.</param>
        /// <returns>True if the PropertyChanged event was raised, false otherwise.</returns>
        [SuppressMessage(
            "Microsoft.Design",
            "CA1006:DoNotNestGenericTypesInMemberSignatures",
            Justification = "This syntax is more convenient than the alternatives."), 
         SuppressMessage(
            "Microsoft.Design", 
            "CA1045:DoNotPassTypesByReference", 
            MessageId = "1#")]
        protected bool Set<T>(
            Expression<Func<T>> propertyExpression,
            ref T field,
            T newValue,
            bool broadcast)
        {
            if (EqualityComparer<T>.Default.Equals(field, newValue))
            {
                return false;
            }

#if !PORTABLE && !SL4
            RaisePropertyChanging(propertyExpression);
#endif
            var oldValue = field;
            field = newValue;
            RaisePropertyChanged(propertyExpression, oldValue, field, broadcast);
            return true;
        }

        /// <summary>
        /// Assigns a new value to the property. Then, raises the
        /// PropertyChanged event if needed, and broadcasts a
        /// PropertyChangedMessage using the Messenger instance (or the
        /// static default instance if no Messenger instance is available). 
        /// </summary>
        /// <typeparam name="T">The type of the property that
        /// changed.</typeparam>
        /// <param name="propertyName">The name of the property that
        /// changed.</param>
        /// <param name="field">The field storing the property's value.</param>
        /// <param name="newValue">The property's value after the change
        /// occurred.</param>
        /// <param name="broadcast">If true, a PropertyChangedMessage will
        /// be broadcasted. If false, only the event will be raised.</param>
        /// <returns>True if the PropertyChanged event was raised, false otherwise.</returns>
        [SuppressMessage(
            "Microsoft.Design", 
            "CA1026:DefaultParametersShouldNotBeUsed"), 
         SuppressMessage(
            "Microsoft.Design", 
            "CA1045:DoNotPassTypesByReference", 
            MessageId = "1#")]
        protected bool Set<T>(
            string propertyName,
            ref T field,
            T newValue = default(T),
            bool broadcast = false)
        {
            if (EqualityComparer<T>.Default.Equals(field, newValue))
            {
                return false;
            }

#if !PORTABLE && !SL4
            RaisePropertyChanging(propertyName);
#endif
            var oldValue = field;
            field = newValue;

            // ReSharper disable ExplicitCallerInfoArgument
            RaisePropertyChanged(propertyName, oldValue, field, broadcast);
            // ReSharper restore ExplicitCallerInfoArgument
            
            return true;
        }

#if CMNATTR
        /// <summary>
        /// Assigns a new value to the property. Then, raises the
        /// PropertyChanged event if needed, and broadcasts a
        /// PropertyChangedMessage using the Messenger instance (or the
        /// static default instance if no Messenger instance is available). 
        /// </summary>
        /// <typeparam name="T">The type of the property that
        /// changed.</typeparam>
        /// <param name="field">The field storing the property's value.</param>
        /// <param name="newValue">The property's value after the change
        /// occurred.</param>
        /// <param name="broadcast">If true, a PropertyChangedMessage will
        /// be broadcasted. If false, only the event will be raised.</param>
        /// <param name="propertyName">(optional) The name of the property that
        /// changed.</param>
        /// <returns>True if the PropertyChanged event was raised, false otherwise.</returns>
        protected bool Set<T>(
            ref T field,
            T newValue = default(T),
            bool broadcast = false,
            [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(field, newValue))
            {
                return false;
            }

#if !PORTABLE
            RaisePropertyChanging(propertyName);
#endif
            var oldValue = field;
            field = newValue;

            // ReSharper disable ExplicitCallerInfoArgument
            RaisePropertyChanged(propertyName, oldValue, field, broadcast);
            // ReSharper restore ExplicitCallerInfoArgument

            return true;
        }
#endif
    }
}


IDE基本基于命令去做,命令有作用域,有的快捷键只是某个控件的,有的是全局的,一个命令的定义离不开RoutedUICommand知识点

接下来知识点就是绑定,不懂的先回去复习下,本文在最后一篇修改外观,前面的外观丑陋皆可以理解


示例命令:

using System.Windows.Input;

namespace Study_DOCK
{
    public class AppCommand
    {
        private static RoutedUICommand newFile;

        static AppCommand()
        {
            InputGestureCollection inputs = new InputGestureCollection();
            AppCommand.newFile = new RoutedUICommand("新建文件", "NewFile", typeof(AppCommand), inputs);
        }


        public static RoutedUICommand NewFile
        {
            get { return AppCommand.newFile; }
        }

    }
}

static构造函数里面实例它,这是最简单的,不包括快捷键和执行,是否执行的。

using System.Windows.Input;

namespace Study_DOCK
{
    public class AppCommand
    {
       
        static AppCommand()
        {
            InputGestureCollection inputs = new InputGestureCollection();
            AppCommand.newFile = new RoutedUICommand("新建文件", "NewFile", typeof(AppCommand), inputs);

            inputs = new InputGestureCollection();
            AppCommand.loadFile = new RoutedUICommand("打开", "LoadFile", typeof(AppCommand), inputs);

            inputs = new InputGestureCollection();
            AppCommand.pinUnpin = new RoutedUICommand("固定\\取消固定", "PinUnpin", typeof(AppCommand), inputs);

            inputs = new InputGestureCollection();
            AppCommand.addMruEntry = new RoutedUICommand("添加到最近列表", "AddEntry", typeof(AppCommand), inputs);

            inputs = new InputGestureCollection();
            AppCommand.removeMruEntry = new RoutedUICommand("从最近列表移除", "RemoveEntry", typeof(AppCommand), inputs);

            inputs = new InputGestureCollection();
            AppCommand.browseURL = new RoutedUICommand("打开URL", "OpenURL", typeof(AppCommand), inputs);

            inputs = new InputGestureCollection();
            AppCommand.showStartPage = new RoutedUICommand("显示起始页", "ShowStartPage", typeof(AppCommand), inputs);
        }


        private static RoutedUICommand newFile;
        public static RoutedUICommand NewFile
        {
            get { return AppCommand.newFile; }
        }


        private static RoutedUICommand loadFile;
        public static RoutedUICommand LoadFile
        {
            get { return AppCommand.loadFile; }
        }




        private static RoutedUICommand pinUnpin;
        public static RoutedUICommand PinUnpin
        {
            get { return AppCommand.pinUnpin; }
        }


        private static RoutedUICommand addMruEntry;
        public static RoutedUICommand AddMruEntry
        {
            get { return AppCommand.addMruEntry; }
        }


        private static RoutedUICommand removeMruEntry;
        public static RoutedUICommand RemoveMruEntry
        {
            get { return AppCommand.removeMruEntry; }
        }

        private static RoutedUICommand browseURL;
        public static RoutedUICommand BrowseURL
        {
            get { return AppCommand.browseURL; }
        }


        private static RoutedUICommand showStartPage;
        public static RoutedUICommand ShowStartPage
        {
            get { return AppCommand.showStartPage; }
        }
    }
}


























参考文章:查看



推荐您阅读更多有关于“WPF4.5avalonDock,”的文章

猜你喜欢

额 本文暂时没人评论 来添加一个吧

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

  查看权限

合肥科大智能常年招聘.NET,Web前端,有想换工作的私聊我AY唯一QQ:875556003和AY交流

抖音号:wpfui,可以看到我的很多作品效果,私活合作请qq联系我

AYUI8社区版Github地址:前往获取

作者:杨洋(AaronYang简称AY,安徽六安人)目前是个人,还没公司AY唯一QQ:875556003和AY交流

高中学历,2015年1月17日开始,兴趣学习研究WPF,目前工作繁忙,不接任何活

声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费.AY主要靠卖技术服务挣钱

不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo

查看捐赠

AYUI7.X MVC教程 更新如下:

第一课 第二课 程序加密教程

vs2015 企业版密钥HM6NR-QXX7C-DFW2Y-8B82K-WTYJV

vs2017 企业版密钥NJVYC-BMHX2-G77MM-4XJMR-6Q8QF

标签列表