• Wpf下AvalonDock使用Prism8进行导航


    参考博客:AvalonDock使用Prism进行导航

    本文不在介绍具体内容,上面那个博客介绍的很详细,这里只补充一下几个细节。

    1.建立一个ViewModel与Avalon进行绑定交互。

     public abstract class DockWindowViewModel : BindableBase, INavigationAware
        {
            #region Properties
    
            #region CloseCommand
            private ICommand _CloseCommand;
            public ICommand CloseCommand
            {
                get
                {
                    if (_CloseCommand == null)
                        _CloseCommand = new DelegateCommand(() => Close());
                    return _CloseCommand;
                }
            }
            #endregion
    
            #region IsClosed
            private bool _IsClosed;
            public bool IsClosed
            {
                get { return _IsClosed; }
                set
                {
                    if (_IsClosed != value)
                    {
                        _IsClosed = value;
                        RaisePropertyChanged("IsClosed");
                    }
                }
            }
            #endregion
    
            #region CanClose
            private bool _CanClose;
            public bool CanClose
            {
                get { return _CanClose; }
                set
                {
                    if (_CanClose != value)
                    {
                        _CanClose = value;
                        RaisePropertyChanged("CanClose");
                    }
                }
            }
            #endregion
    
            #region CanFloat
            private bool _CanFloat;
            public bool CanFloat
            {
                get { return _CanFloat; }
                set
                {
                    if (_CanFloat != value)
                    {
                        _CanFloat = value;
                        RaisePropertyChanged("CanFloat");
                    }
                }
            }
            #endregion
    
            #region Title
            private string _Title;
            public string Title
            {
                get { return _Title; }
                set
                {
                    if (_Title != value)
                    {
                        _Title = value;
                        RaisePropertyChanged("Title");
                    }
                }
            }
            #endregion
    
            #region IconSource
    
            private ImageSource _IconSource = null;
            public ImageSource IconSource
            {
                get { return _IconSource; }
                set
                {
                    if (_IconSource != value)
                    {
                        _IconSource = value;
                        RaisePropertyChanged("IconSource");
                    }
                }
            }
    
            #endregion
    
    
            #endregion
    
            #region IsSelected
            private bool _IsSelected;
            public bool IsSelected
            {
                get { return _IsSelected; }
                set
                {
                    if (_IsSelected != value)
                    {
                        _IsSelected = value;
                        RaisePropertyChanged("IsSelected");
                    }
                }
            }
            #endregion
    
            #region MaxTabItemNumber 控制是否可以多开
            public int MaxTabItemNumber { get; set; } = 1;
            public int TabItemNumber { get; set; } = 1;
            #endregion
    
    
    
            public DockWindowViewModel()
            {
                this.CanClose = true;
                this.CanFloat = true;
                this.IsClosed = false;
            }
    
            public virtual void Close()
            {
                this.IsClosed = true;
            }
    
    
            public virtual void OnNavigatedTo(NavigationContext navigationContext)
            {
                IsSelected = true;
            }
    
            public virtual bool IsNavigationTarget(NavigationContext navigationContext)
            {          
                if (TabItemNumber < MaxTabItemNumber)
                {
                    TabItemNumber++;
                    return false;
                }
                else
                {             
                    return true;
                }      
            }
    
            public void OnNavigatedFrom(NavigationContext navigationContext)
            {
    
            }
        }
    

    2.对AvalonDockingRegionAdapter进行改进

    var TitleBinding = new Binding("Title") { Source = item.DataContext };
    BindingOperations.SetBinding(newLayoutDocument, LayoutDocument.TitleProperty, TitleBinding);

    Title是依赖性属性,对依赖性属性进行绑定,ViewModel上直接设置标题Title就是TabItem的标题Title。

    但是CanClose,CanFloat,IconSource不是依赖性属性,无法使用自带的方法进行绑定。引入Kent.Boogaart.Truss.BindingManager进行绑定

    bindingManager.Bindings.Add(new Kent.Boogaart.Truss.TypedBinding<DockWindowViewModel, LayoutDocument>(viewModel, tm => tm.CanClose, newLayoutDocument, d => d.CanClose) { Mode = Kent.Boogaart.Truss.BindingMode.OneWayToSource });
    bindingManager.Bindings.Add(new Kent.Boogaart.Truss.TypedBinding<DockWindowViewModel, LayoutDocument>(viewModel, tm => tm.CanFloat, newLayoutDocument, d => d.CanFloat) { Mode = Kent.Boogaart.Truss.BindingMode.OneWayToSource });
    bindingManager.Bindings.Add(new Kent.Boogaart.Truss.TypedBinding<DockWindowViewModel, LayoutDocument>(viewModel, tm => tm.IconSource, newLayoutDocument, d => d.IconSource) { Mode = Kent.Boogaart.Truss.BindingMode.OneWayToSource });
    bindingManager.Bindings.Add(new Kent.Boogaart.Truss.TypedBinding<DockWindowViewModel, LayoutDocument>(viewModel, tm => tm.IsSelected, newLayoutDocument, d => d.IsSelected) { Mode = Kent.Boogaart.Truss.BindingMode.TwoWay });

    前三项不是必须项,最后那个IsSelected很重要,用来控制TabItem的激活。


    AvalonDockingRegionAdapter完整代码如下

    using Prism.Regions;
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Threading;
    using Xceed.Wpf.AvalonDock;
    using Xceed.Wpf.AvalonDock.Layout;
    
    namespace AIStudio.Wpf.AvalonDockPrism.Avalon
    {
        public class AvalonDockingRegionAdapter : RegionAdapterBase<DockingManager>
        {
            #region Constructor
    
            public AvalonDockingRegionAdapter(IRegionBehaviorFactory factory): base(factory)
            {
                bindingManager = new Kent.Boogaart.Truss.BindingManager();
            }
    
            #endregion  //Constructor
    
    
            #region Overrides
    
            protected override IRegion CreateRegion()
            {
                return new AllActiveRegion();
            }
    
            protected override void Adapt(IRegion region, DockingManager regionTarget)
            {
    
                region.Views.CollectionChanged += delegate (
                    Object sender, NotifyCollectionChangedEventArgs e)
                {
                    this.OnViewsCollectionChanged(sender, e, region, regionTarget);
                };
    
                regionTarget.DocumentClosed += delegate (
                                Object sender, DocumentClosedEventArgs e)
                {
                    this.OnDocumentClosedEventArgs(sender, e, region);
                };
    
               
            }
    
            #endregion  //Overrides
    
    
            #region Event Handlers
    
            private Kent.Boogaart.Truss.BindingManager bindingManager;
    
            /// <summary>
            /// Handles the NotifyCollectionChangedEventArgs event.
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="e">The event.</param>
            /// <param name="region">The region.</param>
            /// <param name="regionTarget">The region target.</param>
            void OnViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, IRegion region, DockingManager regionTarget)
            {
                if (e.Action == NotifyCollectionChangedAction.Add)
                {
                    foreach (FrameworkElement item in e.NewItems)
                    {
                        UIElement view = item as UIElement;
    
                        if (view != null)
                        {
                            //Create a new layout document to be included in the LayoutDocuemntPane (defined in xaml)
                            LayoutDocument newLayoutDocument = new LayoutDocument();
                            //Set the content of the LayoutDocument
                            newLayoutDocument.Content = item;
    
                            var TitleBinding = new Binding("Title") { Source = item.DataContext };
                            BindingOperations.SetBinding(newLayoutDocument, LayoutDocument.TitleProperty, TitleBinding);
    
                            DockWindowViewModel viewModel = (DockWindowViewModel)item.DataContext;
                            if (viewModel != null)
                            {
                                newLayoutDocument.CanClose = viewModel.CanClose;
                                newLayoutDocument.CanFloat = viewModel.CanFloat;
                                newLayoutDocument.IconSource = viewModel.IconSource;
           
                                bindingManager.Bindings.Add(new Kent.Boogaart.Truss.TypedBinding<DockWindowViewModel, LayoutDocument>(viewModel, tm => tm.CanClose, newLayoutDocument, d => d.CanClose) { Mode = Kent.Boogaart.Truss.BindingMode.OneWayToSource });
                                bindingManager.Bindings.Add(new Kent.Boogaart.Truss.TypedBinding<DockWindowViewModel, LayoutDocument>(viewModel, tm => tm.CanFloat, newLayoutDocument, d => d.CanFloat) { Mode = Kent.Boogaart.Truss.BindingMode.OneWayToSource });
                                bindingManager.Bindings.Add(new Kent.Boogaart.Truss.TypedBinding<DockWindowViewModel, LayoutDocument>(viewModel, tm => tm.IconSource, newLayoutDocument, d => d.IconSource) { Mode = Kent.Boogaart.Truss.BindingMode.OneWayToSource });
                                bindingManager.Bindings.Add(new Kent.Boogaart.Truss.TypedBinding<DockWindowViewModel, LayoutDocument>(viewModel, tm => tm.IsSelected, newLayoutDocument, d => d.IsSelected) { Mode = Kent.Boogaart.Truss.BindingMode.TwoWay });
                            }     
    
                            //Store all LayoutDocuments already pertaining to the LayoutDocumentPane (defined in xaml)
                            List<LayoutDocument> oldLayoutDocuments = new List<LayoutDocument>();
                            //Get the current ILayoutDocumentPane ... Depending on the arrangement of the views this can be either 
                            //a simple LayoutDocumentPane or a LayoutDocumentPaneGroup
                            ILayoutDocumentPane currentILayoutDocumentPane = (ILayoutDocumentPane)regionTarget.Layout.RootPanel.Children[0];
    
                            if (currentILayoutDocumentPane.GetType() == typeof(LayoutDocumentPaneGroup))
                            {
                                //If the current ILayoutDocumentPane turns out to be a group
                                //Get the children (LayoutDocuments) of the first pane
                                LayoutDocumentPane oldLayoutDocumentPane = (LayoutDocumentPane)currentILayoutDocumentPane.Children.ToList()[0];
                                foreach (LayoutDocument child in oldLayoutDocumentPane.Children)
                                {
                                    oldLayoutDocuments.Insert(0, child);
                                }
                            }
                            else if (currentILayoutDocumentPane.GetType() == typeof(LayoutDocumentPane))
                            {
                                //If the current ILayoutDocumentPane turns out to be a simple pane
                                //Get the children (LayoutDocuments) of the single existing pane.
                                foreach (LayoutDocument child in currentILayoutDocumentPane.Children)
                                {
                                    oldLayoutDocuments.Insert(0, child);
                                }
                            }
    
                            //Create a new LayoutDocumentPane and inserts your new LayoutDocument
                            LayoutDocumentPane newLayoutDocumentPane = new LayoutDocumentPane();
                            newLayoutDocumentPane.InsertChildAt(0, newLayoutDocument);
    
                            //Append to the new LayoutDocumentPane the old LayoutDocuments
                            foreach (LayoutDocument doc in oldLayoutDocuments)
                            {
                                newLayoutDocumentPane.InsertChildAt(0, doc);
                            }
    
                            //Traverse the visual tree of the xaml and replace the LayoutDocumentPane (or LayoutDocumentPaneGroup) in xaml
                            //with your new LayoutDocumentPane (or LayoutDocumentPaneGroup)
                            if (currentILayoutDocumentPane.GetType() == typeof(LayoutDocumentPane))
                                regionTarget.Layout.RootPanel.ReplaceChildAt(0, newLayoutDocumentPane);
                            else if (currentILayoutDocumentPane.GetType() == typeof(LayoutDocumentPaneGroup))
                            {
                                currentILayoutDocumentPane.ReplaceChild(currentILayoutDocumentPane.Children.ToList()[0], newLayoutDocumentPane);
                                regionTarget.Layout.RootPanel.ReplaceChildAt(0, currentILayoutDocumentPane);
                            }
                            newLayoutDocument.IsActive = true;
    
                            App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() =>
                            {
                                newLayoutDocument.IsSelected = true;
                            }));
                        }
                    }
                }
            }
    
            /// <summary>
            /// Handles the DocumentClosedEventArgs event raised by the DockingNanager when
            /// one of the LayoutContent it hosts is closed.
            /// </summary>
            /// <param name="sender">The sender</param>
            /// <param name="e">The event.</param>
            /// <param name="region">The region.</param>
            void OnDocumentClosedEventArgs(object sender, DocumentClosedEventArgs e, IRegion region)
            {
                region.Remove(e.Document.Content);
            }
    
            #endregion   
        }
    }
    

     

    最后,老规矩,上完整源码地址:https://gitee.com/akwkevin/AIStudio.Wpf.AvalonDockPrism

    有点更新,请看本文的后续2,如果要看本文源码,需要看源码历史记录了。

    作者:竹天笑
    互相学习,提高自己。
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    【NLP-09】textCNN
    【NLP-08】textRNN
    【NLP-07】GloVe(Global Vectors for Word Representation)
    【NLP-06】fastText文本分类算法
    【NLP-05】Doc2vec
    mongo用户认证
    find直接copy大于某一个时间小于某一个时间的文件
    es的settings设置详解
    py笔记第一篇
    Linux inode节点使用率过大处理办法
  • 原文地址:https://www.cnblogs.com/akwkevin/p/14320561.html
Copyright © 2020-2023  润新知