AvalonDock与Prism区域适配器

6
我在SO上看到了一些问题,但似乎都不适用于我。我想要能够使用伟大的Avalondock 2.0和Prism 4。然而,所有的示例区域适配器都是针对Avalondock 1.x系列的,我无法让它正常工作。
有没有人有关于如何为AvalonDock的LayoutDocumentPane和LayoutAnchorablePane创建区域适配器的示例代码?
1个回答

9

很遗憾,据我所知,“LayoutDocumentPane”和“LayoutAnchorablePane”均不允许包含/创建RegionAdapters,但是“DockingManager”可以。一种解决方案是为“DockingManager”创建一个 RegionAdapter ,然后在可视树中管理“LayoutDocuments”的实例化。

xaml如下:

<ad:DockingManager Background="AliceBlue" x:Name="WorkspaceRegion" prism:RegionManager.RegionName="WorkspaceRegion">
                        <ad:LayoutRoot>
                            <ad:LayoutPanel>
                                <ad:LayoutDocumentPaneGroup>
                                    <ad:LayoutDocumentPane>

                                    </ad:LayoutDocumentPane>
                                </ad:LayoutDocumentPaneGroup>
                            </ad:LayoutPanel>
                        </ad:LayoutRoot>
                    </ad:DockingManager>

请注意,区域是在DockingManager标记中定义的,并且在LayoutPanel下存在一个单独的LayoutDocumentPaneGroup。 LayoutDocumentPaneGroup下的LayoutDocumentPane将托管与要添加到“WorkspaceRegion”的视图相关联的LayoutDocuments。
至于RegionAdapter本身,请参考我提供带有说明注释的以下代码。
#region Constructor

        public AvalonDockRegionAdapter(IRegionBehaviorFactory factory)
            : base(factory)
        {
        }

        #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

        /// <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;

                        ViewModelBase_2 viewModel = (ViewModelBase_2)item.DataContext;

                        if (viewModel != null)
                        {
                            //All my viewmodels have properties DisplayName and IconKey
                            newLayoutDocument.Title = viewModel.DisplayName;
                            //GetImageUri is custom made method which gets the icon for the LayoutDocument
                            newLayoutDocument.IconSource = this.GetImageUri(viewModel.IconKey);
                        }

                        //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;
                    }
                }
            }
        }

        /// <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  //Event handlers

请不要忘记在您的启动器中添加以下代码,以便Prism知道您的RegionAdapter的存在。
protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
        {
            // Call base method
            var mappings = base.ConfigureRegionAdapterMappings();
            if (mappings == null) return null;

            // Add custom mappings
            mappings.RegisterMapping(typeof(DockingManager),
                ServiceLocator.Current.GetInstance<AvalonDockRegionAdapter>());

            // Set return value
            return mappings;
        }

好的。我知道这不是最清晰的解决方案,但它应该可以工作。同样的方法也可以轻松应用到“LayoutAnchorablePane”上。

长命百岁,繁荣昌盛!


我有LayoutAnchorablePane和LayoutAnchorableDocument的适配器,但有时它会注册适配器..有时不会。非常令人沮丧。 - Vlad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接