Features
- Support MVVM with Prism
- Supports ViewModel First or ViewFirst Approach
- Supports styling RadPane in xaml rather than DockingPansFactory
- Code RadDocking – SourceCode
The XAML
- Defiine the region names at RadPaneGroup level
- Set Rad Panel Style via ItemContainerStyle
- Bind Header property of RadPane with Title Property in View Model
<Window.Resources>
<Style x:Key="RadPaneFactoryStyle" TargetType="{x:Type telerik:RadPane}">
<Setter Property="Header" Value="{Binding Title}"/>
</Style>
</Window.Resources>
<Grid>
<telerikDocking:RadDocking>
<telerikDocking:RadDocking.DocumentHost>
<telerikDocking:RadSplitContainer >
<telerikDocking:RadPaneGroup regions:RegionManager.RegionName="MainRegion"
ItemContainerStyle="{StaticResource RadPaneFactoryStyle}"
>
</telerikDocking:RadPaneGroup>
</telerikDocking:RadSplitContainer>
</telerikDocking:RadDocking.DocumentHost>
<telerikDocking:RadSplitContainer InitialPosition="DockedRight">
<telerikDocking:RadPaneGroup regions:RegionManager.RegionName="MainRegion1" >
</telerikDocking:RadPaneGroup>
</telerikDocking:RadSplitContainer>
</telerikDocking:RadDocking>
</Grid>
Configure Region Adapter Mappings in Bootstrap
protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
{
var mappings = base.ConfigureRegionAdapterMappings();
mappings.RegisterMapping(typeof(RadPaneGroup), this.Container.Resolve<RadPaneGroupRegionAdapter>());
return mappings;
}
Define the RadPaneGroup RegionAdapter
Behavior
public class RadPaneGroupRegionAdapter : RegionAdapterBase<RadPaneGroup>
{
public RadPaneGroupRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
: base(regionBehaviorFactory)
{
}
protected override void Adapt(IRegion region, RadPaneGroup regionTarget)
{
var docking = regionTarget.ParentOfType<RadDocking>();
if (docking.DockingPanesFactory == null)
{
docking.DockingPanesFactory = new CustomDockingPanesFactory();
}
var store = DocumentsStoreAttachment.GetPanesStore(docking);
if (store == null)
{
store = new PanesStore();
DocumentsStoreAttachment.SetPanesStore(docking, store);
BindingOperations.SetBinding(
docking,
RadDocking.PanesSourceProperty,
new Binding("PanesSource") { Source = store });
}
}
protected override IRegion CreateRegion()
{
return new SingleActiveRegion();
}
protected override void AttachBehaviors(IRegion region, RadPaneGroup regionTarget)
{
if (region == null)
throw new System.ArgumentNullException("region");
var docking = regionTarget.ParentOfType<RadDocking>();
// Add the behavior that syncs the items source items with the rest of the items
region.Behaviors.Add(RadPaneGroupSyncBehavior.BehaviorKey, new RadPaneGroupSyncBehavior()
{
HostControl = regionTarget,
Docking = docking
});
base.AttachBehaviors(region, regionTarget);
}
private class PanesStore
{
public readonly ObservableCollection<object> Panes = new ObservableCollection<object>();
ReadOnlyObservableCollection<object> _readonlyDocumentsList;
public ReadOnlyObservableCollection<object> PanesSource
{
get
{
return _readonlyDocumentsList ??
(_readonlyDocumentsList = new ReadOnlyObservableCollection<object>(Panes));
}
}
}
private static class DocumentsStoreAttachment
{
public static readonly DependencyProperty PanesStoreProperty = DependencyProperty.RegisterAttached(
"PanesStore",
typeof(PanesStore),
typeof(DocumentsStoreAttachment),
new PropertyMetadata(null)
);
public static void SetPanesStore(UIElement element, PanesStore value)
{
element.SetValue(PanesStoreProperty, value);
}
public static PanesStore GetPanesStore(UIElement element)
{
return (PanesStore)element.GetValue(PanesStoreProperty);
}
}
private class CustomDockingPanesFactory : DockingPanesFactory
{
public RadPaneGroup ActiveGroup { get; internal set; }
protected override void AddPane(RadDocking radDocking, RadPane pane)
{
var group = ActiveGroup;
pane.SetValue(RadPane.HeaderProperty, DependencyProperty.UnsetValue);
var style = group.ItemContainerStyle;
if (style != null)
{
pane.SetValue(RadPane.StyleProperty, style);
}
group?.Items.Add(pane);
}
}
private class RadPaneGroupSyncBehavior : RegionBehavior, IHostAwareRegionBehavior
{
public static readonly string BehaviorKey = "RadPaneGroupSyncBehavior";
private bool _updatingActiveViewsInManagerActiveContentChanged;
private RadPaneGroup _radPaneGroup;
private PanesStore _documentStore;
public DependencyObject HostControl
{
get
{
return _radPaneGroup;
}
set
{
_radPaneGroup = value as RadPaneGroup;
}
}
public RadDocking Docking { get; internal set; }
/// <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 = _radPaneGroup.ItemsSource != null;
if (itemsSourceIsSet)
{
throw new InvalidOperationException();
}
SynchronizeItems();
Docking.ActivePaneChanged += ManagerActiveContentChanged;
Region.ActiveViews.CollectionChanged += ActiveViews_CollectionChanged;
Region.Views.CollectionChanged += Views_CollectionChanged;
Docking.Close += _dockingManager_DocumentClosed;
}
private void _dockingManager_DocumentClosed(object sender, StateChangeEventArgs e)
{
foreach (var pane in e.Panes)
{
if (Region.Views.Contains(pane.Content))
{
Region.Remove(pane.Content);
}
}
}
private void Views_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
int startIndex = e.NewStartingIndex;
foreach (var newItem in e.NewItems)
{
var panesFactory = ((CustomDockingPanesFactory)Docking.DockingPanesFactory);
panesFactory.ActiveGroup = _radPaneGroup;
_documentStore.Panes.Insert(0, newItem);
}
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (object oldItem in e.OldItems)
{
_documentStore.Panes.Remove(oldItem);
}
}
}
private void SynchronizeItems()
{
var store = DocumentsStoreAttachment.GetPanesStore(Docking);
_documentStore = store;
foreach (object view in Region.Views)
{
((CustomDockingPanesFactory)Docking.DockingPanesFactory).ActiveGroup = _radPaneGroup;
_documentStore.Panes.Insert(0, view);
}
}
private void ActiveViews_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_updatingActiveViewsInManagerActiveContentChanged)
{
return;
}
if (e.Action == NotifyCollectionChangedAction.Add)
{
if (Docking.ActivePane != null
&& Docking.ActivePane != e.NewItems[0]
&& Region.ActiveViews.Contains(Docking.ActivePane.Content))
{
Region.Deactivate(Docking.ActivePane.Content);
}
var pane = Docking.Panes.FirstOrDefault(x => x.Content.Equals(e.NewItems[0]));
Docking.ActivePane = pane;
}
else if (e.Action == NotifyCollectionChangedAction.Remove &&
e.OldItems.Contains(Docking.ActivePane))
{
Docking.ActivePane = null;
}
}
private void ManagerActiveContentChanged(object sender, EventArgs e)
{
try
{
_updatingActiveViewsInManagerActiveContentChanged = true;
if (Docking.Equals(sender))
{
var activePane = Docking.ActivePane;
if (activePane != null)
{
var activeViews = Region.ActiveViews.Where(it => it != activePane.Content).ToList();
foreach (var item in activeViews)
{
Region.Deactivate(item);
}
if (Region.Views.Contains(activePane.Content) && !Region.ActiveViews.Contains(activePane.Content))
{
Region.Activate(activePane.Content);
}
}
}
}
finally
{
_updatingActiveViewsInManagerActiveContentChanged = false;
}
}
}
}

Leave a comment