带有棱镜区域适配器的AvalonDock

我已经看到了一些关于SO的问题,但它们似乎都不适用于我。 我希望能够使用带有棱镜4的伟大的Avalondock 2.0 。然而,所有的样本区域适配器都适用于Avalondock 1.x系列,我无法使其正常工作。

有没有人有关于如何为AvalonDock的LayoutDocumentPane和LayoutAnchorablePane创建Region Adapter的示例代码?

不幸的是,据我所知,“LayoutDocumentPane”和“LayoutAnchorablePane”都不允许包含/创建RegionAdapters,但是“DockingManager”会这样做。 一种解决方案是为DockingManager创建RegionAdapter ,然后管理可视树中“LayoutDocuments”的实例化。

xaml看起来如下:

          

请注意,该区域在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 ///  /// Handles the NotifyCollectionChangedEventArgs event. ///  /// The sender. /// The event. /// The region. /// The region target. 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 oldLayoutDocuments = new List(); //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; } } } } ///  /// Handles the DocumentClosedEventArgs event raised by the DockingNanager when /// one of the LayoutContent it hosts is closed. ///  /// The sender /// The event. /// The region. 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()); // Set return value return mappings; } 

瞧。 我知道这不是最干净的解决方案,但应该有效。 同样的方法可以很容易地应用于“LayoutAnchorablePane”。

健康长寿·繁荣昌盛!