I'm trying to figure out how to work with AvalonDock in Prism. My MainApplciationView Xaml code:
<Window x:Class="WPFTestLab.Views.ApplicationWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:fa="http://schemas.fontawesome.com/icons/"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
xmlns:core="clr-namespace:WPFTestLab.Core;assembly=WPFTestLab.Core"
xmlns:avalonDock="https://github.com/Dirkster99/AvalonDock"
Title="{Binding Title}" Width="1280" Height="720" WindowStartupLocation="CenterScreen">
<Grid>
<avalonDock:DockingManager prism:RegionManager.RegionName="{x:Static core:RegionNames.MainRegion}">
<avalonDock:LayoutRoot>
<avalonDock:LayoutPanel Orientation="Horizontal">
<avalonDock:LayoutDocumentPaneGroup DockWidth="100" Orientation="Vertical">
<avalonDock:LayoutDocumentPane>
</avalonDock:LayoutDocumentPane>
</avalonDock:LayoutDocumentPaneGroup>
</avalonDock:LayoutPanel>
</avalonDock:LayoutRoot>
</avalonDock:DockingManager>
</Grid>
And I create docking manager region adapter:
public class AvalonDockingRegionAdapter : RegionAdapterBase<DockingManager>
{
private bool _updatingActiveViewsInManagerActiveContentChanged;
#region Constructor
public AvalonDockingRegionAdapter(IRegionBehaviorFactory factory)
: base(factory)
{
_updatingActiveViewsInManagerActiveContentChanged = false;
}
#endregion //Constructor
#region Overrides
protected override IRegion CreateRegion()
{
return new SingleActiveRegion();
}
protected override void Adapt(IRegion region, DockingManager regionTarget)
{
regionTarget.ActiveContentChanged += delegate (
object sender, EventArgs e)
{
this.ManagerActiveContentChanged(sender, e, region, regionTarget);
};
region.Views.CollectionChanged += delegate (
Object sender, NotifyCollectionChangedEventArgs e)
{
this.OnViewsCollectionChanged(sender, e, region, regionTarget);
};
region.Views.CollectionChanged += delegate (
Object sender, NotifyCollectionChangedEventArgs e)
{
this.OnActiveViewsCollectionChanged(sender, e, region, regionTarget);
};
regionTarget.DocumentClosed += delegate (
Object sender, DocumentClosedEventArgs e)
{
this.OnDocumentClosedEventArgs(sender, e, region);
};
}
private void OnActiveViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, IRegion region, DockingManager regionTarget)
{
if (_updatingActiveViewsInManagerActiveContentChanged) return;
if (e.Action == NotifyCollectionChangedAction.Add)
{
if (regionTarget.ActiveContent != null && regionTarget.ActiveContent != e.NewItems[0] &&
region.ActiveViews.Contains(regionTarget.ActiveContent))
region.Deactivate(regionTarget.ActiveContent);
regionTarget.ActiveContent = e.NewItems[0];
}
else if (e.Action == NotifyCollectionChangedAction.Remove &&
e.OldItems.Contains(regionTarget.ActiveContent))
{
regionTarget.ActiveContent = null;
}
}
private void ManagerActiveContentChanged(object sender, EventArgs e, IRegion region, DockingManager regionTarget)
{
try
{
_updatingActiveViewsInManagerActiveContentChanged = true;
if (regionTarget == sender)
{
var activeContent = regionTarget.ActiveContent;
if (activeContent != null)
{
foreach (var item in region.ActiveViews.Where(it => it != activeContent))
if (region.Views.Contains(item))
region.Deactivate(item);
if (region.Views.Contains(activeContent) && !region.ActiveViews.Contains(activeContent))
region.Activate(activeContent);
}
}
}
finally
{
_updatingActiveViewsInManagerActiveContentChanged = false;
}
}
#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();
newLayoutDocument.Content = item;
PaneViewModel viewModel = (PaneViewModel)item.DataContext;
if (viewModel != null)
newLayoutDocument.Title = viewModel.Title;
//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
}
My question is how I can manipulate docking manager from MainApplicationViewModel. For example, I want to catch the active document content change and disable button in MainApplicationView. Or clicking the button in MainApplicationView should change the text in current active document view.