Вопрос по wpf, c# – AvalonDock с адаптером региона призмы

6

Я видел некоторые вопросы по SO, но ни один из них не показался мне подходящим. Я хочу иметь возможность использовать великийАвалондок 2.0 с Prism 4. Тем не менее, все адаптеры областей выборки для этого для серии Avalondock 1.x, что я не могу заставить его работать.

У кого-нибудь есть пример кода о том, как создать адаптер региона для AvalonDock's LayoutDocumentPane и LayoutAnchorablePane?

Ваш Ответ

1   ответ
9

LayoutDocumentPane & quot; и & quot; LayoutAnchorablePane & quot; не разрешать включение / создание RegionAdapters, однако & quot; DockingManager & quot; делает. Одним из решений будет созданиеRegionAdapter for the DockingManager который затем будет управлять созданием & lt; LayoutDocuments & quot; в визуальном дереве.

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. LayoutDocumentPane в LayoutDocumentPaneGroup будет размещать LayoutDocuments, связанные с представлениями, которые будут добавлены в «WorkspaceRegion».

Что касается самого 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

Не забудьте добавить приведенный ниже код в ваш Bootstrapper, чтобы 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;
        }

Voil & # xE0 ;. Я знаю, что это не самое чистое решение, но оно должно работать. Тот же самый подход может быть легко применен к «LayoutAnchorablePane».

Живи долго и процветай!

Я счастлив, что сделал. :-)
У меня есть адаптеры для LayoutAnchorablePane и LayoutAnchorableDocument, и иногда он регистрирует адаптеры .. иногда нет. Очень расстраивает.
+1: часть наILayoutDocumentPane помог мне

Похожие вопросы