2009-05-29 10 views

Répondre

0

Mon conseil serait de regarder dans Microsoft.Practices.Composite.Presentation.Regions dans la source de Prism. Plus précisément, jetez un oeil à ItemsControlRegionAdapter et utilisez-le comme un modèle. Rappelez-vous d'hériter de RegionAdapterBase <>:

public class ItemsControlRegionAdapter : RegionAdapterBase<ItemsControl> 

et de passer outre ConfigureRegionAdapterMappings() dans le programme d'amorçage. Cela ressemblerait à quelque chose comme:

protected override RegionAdapterMappings ConfigureRegionAdapterMappings() 
{ 
    RegionAdapterMappings mappings = base.ConfigureRegionAdapterMappings(); 
    mappings.RegisterMapping(typeof(Canvas), Container.Resolve<CanvasRegionAdapter>()); 
    return mappings; 
} 
4

Markus Raufer a ajouté deux adaptateurs de la région au projet CompositeWpfContrib à CodePlex qui prend en charge les DocumentPane et DockingPane.

2

Depuis l'Avalon DocumentPane et DockingPane sont tous deux basés sur la System.Windows.Controls.Primitives.Selector vous pouvez utiliser la SelectorRegionAdapter par défaut dans Prism.

basons juste votre contrôle sur DockableContent

<ad:DockableContent x:Class="DesignerWPF.UserControl1" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock" 
      d:DesignHeight="300" d:DesignWidth="300" Title="dans"> 
    <Grid> 
     <TextBox Text="sdfdf"></TextBox> 
    </Grid> 
</ad:DockableContent> 

sur votre principale Shell.xmal définir les régions dans le dockablepane

 <ad:DockingManager x:Name="dockManager" Grid.Row="1" Margin="0,4,0,0"> 
      <ad:ResizingPanel Orientation="Horizontal"> 
       <ad:DockablePane cal:RegionManager.RegionName="LeftRegion"> 

       </ad:DockablePane> 
       <ad:DocumentPane cal:RegionManager.RegionName="DocumentRegion"> 

       </ad:DocumentPane> 
      </ad:ResizingPanel> 
     </ad:DockingManager> 

puis lorsque vous initialisez votre présentateur pour votre contrôle, il va s'affiche dans le quai.

public class UserTestControl : IModule 
    { 
     public UserTestControl(IUnityContainer container, IRegionManager regionManager) 
     { 
      Container = container; 
      RegionManager = regionManager; 
     } 
     public void Initialize() 
     { 
      var addFundView = Container.Resolve<UserControl1>(); 
      RegionManager.Regions["LeftRegion"].Add(addFundView); 
     } 

     public IUnityContainer Container { get; private set; } 
     public IRegionManager RegionManager { get; private set; } 
    } 
3

J'ai utilisé Raffaeu Bermuda extraits pour soutenir adaptateur région onglet Avalon, mais a constaté qu'il ya certains problèmes ne sont pas résolus:

1- Il ne supporte pas Activation aa certaine vue (aka - onglet - DockableContent), donc le code Region.Activate(object view) ne fonctionnera pas.

2- Tous les onglets sont actifs par défaut dans la région. Donc Region.ActiveViews collection par défaut a toutes les vues, ce n'est pas idéal, comme parfois j'ai besoin de vérifier si une vue est active ou non (vous pouvez imaginer un bouton de sauvegarde sur une barre d'outils qui exécute un SaveCommand uniquement sur la vue active courante = onglet dans notre cas)

3- Les vues fermées ne sont pas réellement fermées, seulement masquées. Même si vous définissez le HideOnClose = true lors de l'ajout du nouveauDockableContent, il n'est toujours pas supprimé de la collection Region.Views. Cela pourrait entraîner des problèmes de fuite de mémoire.

4- Si vous avez déjà ajouté un contenu DockableContent dans le volet, ils ne seront pas synchronisés et ajoutés à la collection Region.Views.

Donc voici le code que je me sers maintenant, il est juste un petit coup sec de l'adaptateur de sélection et Sélecteur de synchronisation Comportement trouvé dans le code source PRISM:

AvalonRegionAdapter Classe:

public class AvalonRegionAdapter : RegionAdapterBase<DocumentPane> 
{ 
    public AvalonRegionAdapter(IRegionBehaviorFactory factory) : base(factory) {} 

    protected override void AttachBehaviors(IRegion region, DocumentPane regionTarget) 
    { 
     if (region == null) throw new System.ArgumentNullException("region"); 
     //Add the behavior that syncs the items source items with the rest of the items 
     region.Behaviors.Add(AvalonDocumentSyncBehavior.BehaviorKey, 
          new AvalonDocumentSyncBehavior() 
     { 
      HostControl = regionTarget 
     }); 
     base.AttachBehaviors(region, regionTarget); 
    } 

    protected override void Adapt(IRegion region, DocumentPane regionTarget){ } 

    protected override IRegion CreateRegion() 
    { 
     return new Region(); 
    } 
} 

AvalonDocumentSyncBehavior code Comportement:

public class AvalonDocumentSyncBehavior : RegionBehavior, IHostAwareRegionBehavior 
{ 
    /// <summary> 
    /// Name that identifies the SelectorItemsSourceSyncBehavior behavior in a collection of RegionsBehaviors. 
    /// </summary> 
    public static readonly string BehaviorKey = "AvalonDocumentSyncBehavior"; 
    private bool updatingActiveViewsInHostControlSelectionChanged; 
    private Selector hostControl; 

    /// <summary> 
    /// Gets or sets the <see cref="DependencyObject"/> that the <see cref="IRegion"/> is attached to. 
    /// </summary> 
    /// <value> 
    /// A <see cref="DependencyObject"/> that the <see cref="IRegion"/> is attached to. 
    /// </value> 
    /// <remarks>For this behavior, the host control must always be a <see cref="Selector"/> or an inherited class.</remarks> 
    public DependencyObject HostControl 
    { 
     get 
     { 
      return this.hostControl; 
     } 

     set 
     { 
      this.hostControl = value as Selector; 
     } 
    } 

    /// <summary> 
    /// Starts to monitor the <see cref="IRegion"/> to keep it in synch with the items of the <see cref="HostControl"/>. 
    /// </summary> 
    protected override void OnAttach() 
    { 
     bool itemsSourceIsSet = this.hostControl.ItemsSource != null; 
     if (itemsSourceIsSet) 
     { 
      //throw new InvalidOperationException(Resources.ItemsControlHasItemsSourceException); 
     } 

     this.SynchronizeItems(); 

     this.hostControl.SelectionChanged += this.HostControlSelectionChanged; 
     this.Region.ActiveViews.CollectionChanged += this.ActiveViews_CollectionChanged; 
     this.Region.Views.CollectionChanged += this.Views_CollectionChanged; 
    } 

    private void Views_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.Action == NotifyCollectionChangedAction.Add) 
     { 
      int startIndex = e.NewStartingIndex; 
      foreach (object newItem in e.NewItems) 
      { 
       UIElement view = newItem as UIElement; 
       TabViewModel viewModel = ((UserControl)view).DataContext as TabViewModel; 
       if (view != null) 
       { 
        DockableContent newDockableContent = new DockableContent(); 
        newDockableContent.Content = newItem; 
        //if associated view has metadata then apply it. 
        newDockableContent.Title = view.GetType().ToString(); 
        if (viewModel != null) 
        { 
         //Image img = new Image(); 
         //img.Source = new BitmapImage(new Uri(@"Resources/Alerts.png", UriKind.Relative)); 
         newDockableContent.Title = viewModel.TabModel.Title; 
         newDockableContent.IsCloseable = viewModel.TabModel.CanClose; 
         //newContentPane.Icon = img.Source; 
        } 

        //When contentPane is closed remove from the associated region 
        newDockableContent.Closed += new EventHandler(newDockableContent_Closed); 

        newDockableContent.HideOnClose = false; 
        this.hostControl.Items.Add(newDockableContent); 
        newDockableContent.Activate(); 
       } 
      } 
     } 
     else if (e.Action == NotifyCollectionChangedAction.Remove) 
     { 
      foreach (object oldItem in e.OldItems) 
      { 
       this.hostControl.Items.Remove(oldItem); 
      } 
     } 
    } 

    void newDockableContent_Closed(object sender, EventArgs e) 
    { 
     var dockableContent = sender as DockableContent; 
     if(dockableContent != null) 
      if (this.Region.Views.Contains(dockableContent.Content)) 
      { 
       this.Region.Remove(dockableContent.Content); 
      } 
    } 

    private void SynchronizeItems() 
    { 
     List<object> existingItems = new List<object>(); 

     // Control must be empty before "Binding" to a region 
     foreach (object childItem in this.hostControl.Items) 
     { 
      existingItems.Add(childItem); 
     } 

     foreach (object view in this.Region.Views) 
     { 
      this.hostControl.Items.Add(view); 
     } 

     foreach (object existingItem in existingItems) 
     { 
      this.Region.Add(existingItem); 
     } 
    } 


    private void ActiveViews_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (this.updatingActiveViewsInHostControlSelectionChanged) 
     { 
      // If we are updating the ActiveViews collection in the HostControlSelectionChanged, that 
      // means the user has set the SelectedItem or SelectedItems himself and we don't need to do that here now 
      return; 
     } 

     if (e.Action == NotifyCollectionChangedAction.Add) 
     { 
      var selectedDockableContent = this.hostControl.SelectedItem as DockableContent; 
      if (selectedDockableContent != null 
       && selectedDockableContent.Content != null 
       && selectedDockableContent.Content != e.NewItems[0] 
       && this.Region.ActiveViews.Contains(selectedDockableContent.Content)) 
      { 
       this.Region.Deactivate(selectedDockableContent.Content); 
      } 

      var _UIElement = e.NewItems[0] as FrameworkElement; 
      this.hostControl.SelectedItem = _UIElement.Parent; 
     } 
     else if (e.Action == NotifyCollectionChangedAction.Remove && 
       e.OldItems.Contains(this.hostControl.SelectedItem)) 
     { 
      this.hostControl.SelectedItem = null; 
     } 
    } 

    private void HostControlSelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     try 
     { 
      // Record the fact that we are now updating active views in the HostControlSelectionChanged method. 
      // This is needed to prevent the ActiveViews_CollectionChanged() method from firing. 
      this.updatingActiveViewsInHostControlSelectionChanged = true; 

      object source; 
      source = e.OriginalSource; 

      if (source == sender) 
      { 
       foreach (object item in e.RemovedItems) 
       { 
        // check if the view is in both Views and ActiveViews collections (there may be out of sync) 
        var dockableContent = item as DockableContent; 
        if (this.Region.Views.Contains(dockableContent.Content) && this.Region.ActiveViews.Contains(dockableContent.Content)) 
        { 
         this.Region.Deactivate(dockableContent.Content); 
        } 
       } 

       foreach (object item in e.AddedItems) 
       { 
        var dockableContent = item as DockableContent; 
        if (this.Region.Views.Contains(dockableContent.Content) && 
         !this.Region.ActiveViews.Contains(dockableContent.Content)) 
        { 
         this.Region.Activate(dockableContent.Content); 
        } 
       } 
      } 
     } 
     finally 
     { 
      this.updatingActiveViewsInHostControlSelectionChanged = false; 
     } 
    } 
} 

C ode sur bootstrapper pour configurer l'adaptateur

protected override RegionAdapterMappings ConfigureRegionAdapterMappings() 
{ 
    var mappings = base.ConfigureRegionAdapterMappings(); 
    mappings.RegisterMapping(typeof(AvalonDock.DocumentPane), 
          this.Container.Resolve<AvalonRegionAdapter>()); 
    return mappings; 
} 

Ensuite, vous devez l'TabModel et TabViewModel à partir Raffaeu Bermuda

public sealed class TabModel : DependencyObject 
{ 
    public string Title 
    { 
     get { return (string)GetValue(TitleProperty); } 
     set { SetValue(TitleProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for Title. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty TitleProperty = 
     DependencyProperty.Register("Title", typeof(string), typeof(TabModel)); 

    public bool CanClose 
    { 
     get { return (bool)GetValue(CanCloseProperty); } 
     set { SetValue(CanCloseProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for CanClose. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty CanCloseProperty = 
     DependencyProperty.Register("CanClose", typeof(bool), typeof(TabModel)); 

    public bool IsModified 
    { 
     get { return (bool)GetValue(IsModifiedProperty); } 
     set { SetValue(IsModifiedProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for IsModified. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty IsModifiedProperty = 
     DependencyProperty.Register("IsModified", typeof(bool), typeof(TabModel)); 

} 

Et TabViewModel agissant en tant que classe de base:

public class TabViewModel : INotifyPropertyChanged 
{ 
    private TabModel _tabModel; 

    public TabModel TabModel 
    { 
     get { return this._tabModel; } 
     set 
     { 
      this._tabModel = value; 
      OnPropertyChanged("TabModel"); 
     } 
    } 
    public TabViewModel() 
    { 
     this.TabModel = new TabModel(); 
     this.TabModel.CanClose = true; 
     this.TabModel.IsModified = false; 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
    public void OnPropertyChanged(string info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
} 

Permettez-moi savoir si vous avez besoin d'aide, je vais poster un blog dans un proche avenir.

Questions connexes