2012-06-05 30 views
6

he visto algunas preguntas sobre SO pero ninguno de ellos parecía aplicable para mí. Quiero poder usar el gran Avalondock 2.0 con Prism 4. Sin embargo, todos los adaptadores de región de muestra para eso son para la serie Avalondock 1.x, que no puedo hacer que funcionen.AvalonDock con adaptador Prisma Región

¿Alguien tiene código de ejemplo sobre cómo crear un adaptador para la Región LayoutDocumentPane y LayoutAnchorablePane de AvalonDock?

Respuesta

9

Lamentablemente, según mi leal saber y entender, tanto el "LayoutDocumentPane" como el "LayoutAnchorablePane" no permiten la inclusión/creación de RegionAdapters, sin embargo, el "DockingManager" sí lo hace. Una solución sería la creación de un RegionAdapter para la DockingManager que luego gestionar la creación de instancias de "LayoutDocuments" dentro del árbol visual.

el XAML se vería de la siguiente manera:

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

Tenga en cuenta que la región se define en la etiqueta DockingManager y no existe una única LayoutDocumentPaneGroup bajo LayoutPanel. El LayoutDocumentPane en el LayoutDocumentPaneGroup alojará los LayoutDocuments asociados a las vistas que se agregarán a la "Región del espacio de trabajo".

cuanto a la propia RegionAdapter se refieren al código debajo de la cual he proporcionado con comentarios explicativos

#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 

No se olvide de añadir el siguiente código en su programa previo para que Prism es consciente de la existencia de su 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à. Sé que esta no es la solución más limpia, pero debería funcionar. El mismo enfoque se puede aplicar fácilmente a "LayoutAnchorablePane".

Larga vida y prosperidad!

+0

1: La parte de 'ILayoutDocumentPane' me ayudó –

+0

estoy feliz que lo hizo. :-) –

+0

Tengo adaptadores para LayoutAnchorablePane y LayoutAnchorableDocument y algunas veces registra los adaptadores ... a veces no. Muy frustrante. – Vlad

Cuestiones relacionadas