2012-06-05 5 views
6

나는 몇 가지 질문을 보았지만 그 중 아무 것도 나에게 적합하지 않은 것으로 보였다. 나는 Avalondock 2.0을 Prism 4와 함께 사용할 수 있기를 원합니다. 그러나 그 모든 샘플 지역 어댑터는 Avalondock 1.x 시리즈 용으로 작동하지 않습니다.프리즘 지역 어댑터가있는 AvalonDock

누구나 AvalonDock의 LayoutDocumentPane 및 LayoutAnchorablePane에 대한 지역 어댑터를 만드는 방법에 대한 샘플 코드가 있습니까?

답변

9

아쉽게도 "LayoutDocumentPane"과 "LayoutAnchorablePane"은 모두 RegionAdapters의 포함/생성을 허용하지 않지만 "DockingManager"는 허용하지 않습니다. 한 가지 해결책은 DockingManager에 대한 RegionAdapter를 작성한 다음 시각적 트리에서 "LayoutDocuments"의 인스턴스를 관리하는 것입니다.

XAML은 다음과 같이 보일 것이다 :이 지역은 DockingManager 태그에 정의되어 있으며 LayoutPanel에서 하나의 LayoutDocumentPaneGroup가 존재

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

참고. 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 

프리즘이 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à. 나는 이것이 해결책의 가장 깨끗한 것이 아니라는 것을 알고 있지만 그것은 효과가있다. 동일한 접근법을 "LayoutAnchorablePane"에 쉽게 적용 할 수 있습니다.

길고 번영하는 라이브!

+0

+1 : 'ILayoutDocumentPane'의 일부가 나를 도왔습니다 –

+0

나는 행복합니다. :-) –

+0

LayoutAnchorablePane 및 LayoutAnchorableDocument에 대한 어댑터가 있으며 때로는 어댑터를 등록하는 경우가 있습니다. 매우 실망합니다. – Vlad