2012-06-05 4 views
6

Tôi đã thấy một số câu hỏi về SO nhưng không có câu hỏi nào trong số chúng có thể áp dụng cho tôi. Tôi muốn có thể sử dụng tuyệt vời Avalondock 2.0 với lăng kính 4. Tuy nhiên, tất cả các bộ điều hợp vùng mẫu cho đó là cho Avalondock 1.x series, mà tôi không thể làm cho nó hoạt động.AvalonDock với Bộ điều hợp Khu vực lăng kính

Có ai có mã mẫu về cách tạo Bộ điều hợp vùng cho LayoutDocumentPane và LayoutAnchorablePane của AvalonDock không?

Trả lời

9

Thật không may, theo hiểu biết tốt nhất của tôi, cả "LayoutDocumentPane" và "LayoutAnchorablePane" không cho phép đưa/tạo RegionAdapters, tuy nhiên, "DockingManager" thực hiện. Một giải pháp là tạo một Vùng phụ cho DockingManager sau đó sẽ quản lý việc khởi tạo "LayoutDocuments" trong cây trực quan.

Các XAML sẽ trông như sau:

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

Lưu ý rằng khu vực được xác định trong thẻ DockingManager và tồn tại một LayoutDocumentPaneGroup đơn dưới LayoutPanel. LayoutDocumentPane trong LayoutDocumentPaneGroup sẽ lưu trữ LayoutDocuments được kết hợp với các khung nhìn được thêm vào "WorkspaceRegion".

Đối với RegionAdapter tự tham khảo các mã dưới đây mà tôi được cung cấp với ý kiến ​​giải thích

#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 

Đừng quên để thêm mã dưới đây vào Bootstrapper của bạn để Prism nhận thức được sự tồn tại của RegionAdapter bạn

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à. Tôi biết đây không phải là giải pháp sạch nhất nhưng nó sẽ hoạt động. Cách tiếp cận tương tự có thể dễ dàng được áp dụng cho "LayoutAnchorablePane".

Sống lâu và thịnh vượng!

+0

+1: Phần trên 'ILayoutDocumentPane' đã giúp tôi thực hiện –

+0

Tôi rất vui vì điều đó. :-) –

+0

Tôi có bộ điều hợp cho LayoutAnchorablePane và LayoutAnchorableDocument và đôi khi nó đăng ký bộ điều hợp .. đôi khi không. Rất bực bội. – Vlad