我看過一些關於SO的問題,但它們都不適用於我。我希望能夠在Prism 4中使用偉大的Avalondock 2.0。但是,所有適用於Avalondock 1.x系列的示例區域適配器都無法正常工作。帶棱鏡區域適配器的AvalonDock
有沒有人有關於如何爲AvalonDock的LayoutDocumentPane和LayoutAnchorablePane創建區域適配器的示例代碼?
我看過一些關於SO的問題,但它們都不適用於我。我希望能夠在Prism 4中使用偉大的Avalondock 2.0。但是,所有適用於Avalondock 1.x系列的示例區域適配器都無法正常工作。帶棱鏡區域適配器的AvalonDock
有沒有人有關於如何爲AvalonDock的LayoutDocumentPane和LayoutAnchorablePane創建區域適配器的示例代碼?
不幸的是,就我所知,「LayoutDocumentPane」和「LayoutAnchorablePane」都不允許包含/創建RegionAdapters,但是「DockingManager」卻可以。一種解決方案是爲DockingManager創建一個RegionAdapter,然後管理可視化樹中「LayoutDocuments」的實例化。
的XAML將如下所示:
<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>
注意該區域在DockingManager標籤定義和存在LayoutPanel下單LayoutDocumentPaneGroup。 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」。
長壽而繁榮!
+1:'ILayoutDocumentPane'上的部分幫助我出局 –
我很高興它做到了。 :-) –
我有適用於LayoutAnchorablePane和LayoutAnchorableDocument的適配器,有時它會註冊適配器..有時不適用。非常令人沮喪。 – Vlad