2009-05-29 3 views

ответ

0

Моим советом было бы посмотреть в Microsoft.Practices.Composite.Presentation.Regions в источнике Prism. В частности, взгляните на элемент ItemsControlRegionAdapter и используйте его в качестве шаблона. Помните, чтобы наследовать от RegionAdapterBase <>:

public class ItemsControlRegionAdapter : RegionAdapterBase<ItemsControl> 

и переопределить ConfigureRegionAdapterMappings() в загрузчике. Это будет выглядеть примерно так:

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

Маркус Raufer добавил два региона адаптеры к проекту CompositeWpfContrib на CodePlex, который поддерживает как DocumentPane и DockingPane.

2

Поскольку Avalon DocumentPane и DockingPane основаны на System.Windows.Controls.Primitives.Selector, вы можете использовать SelectorRegionAdapter по умолчанию в Prism.

Просто BASE свой контроль над 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> 

на главном Shell.xmal установить регионы в 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> 

тогда, когда вы инициализации выступающему для управления он будет получать отображаться в док.

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

Я использовал Raffaeu Bermuda фрагментов для поддержки Avalon вкладки региона адаптера, но обнаружил, что есть некоторые проблемы не решаются:

1- Он не поддерживает Активирование аа определенного вида (он же - вкладка - DockableContent), поэтому код Region.Activate(object view) не будет работать.

2- Все вкладки активны по умолчанию в регионе. Таким образом, коллекция Region.ActiveViews по умолчанию имеет все представления, это не идеально, поскольку иногда мне нужно было проверить, активно или нет представление (вы могли бы представить кнопку сохранения в области панели инструментов, которая выполняет SaveCommand только в текущем активном представлении = tab в нашем случае)

3- Закрытые виды фактически не закрываются, только скрыты. Даже если вы установили HideOnClose = true при добавлении newDockableContent, он по-прежнему не удаляется из коллекции Region.Views. Это может привести к проблемам с утечками памяти.

4 Если у вас есть ранее добавленный DockableContent на панели, они не будут синхронизированы и добавлены в коллекцию Region.Views.

Так вот код, я использую в настоящее время, это всего лишь небольшая настройка от Selector адаптера и выбор синхронизации поведения находится в исходном PRISM кода:

AvalonRegionAdapter Класс:

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 Поведение Код:

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 ода на загрузчике, чтобы настроить адаптер

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

Тогда вам нужен TabModel и TabViewModel, как от 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)); 

} 

и А TabViewModel выступает в качестве базового класса:

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)); 
     } 
    } 
} 

Пусть мне знаете, если вам нужна дополнительная помощь, я опубликую блог в ближайшее время.