Reputation: 11754
I want to add a new event to an existing control.
I'd like to add a new property and an event to a Docking Control. I have access to an event "OnLastActiveDocumentChanged" which return the current active window. From that active window I could retrieve my active viewModel from its DataContext.
I want to add a property "ActiveModel" and an Event "OnActiveModelChanged".
I currently made the behavior with the property but don't know how to add the event ?
Can I add an event in a behavior and how ? I wonder if I would be better writing a blend behavior ?
Code from ActiPro and modified by me:
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Threading;
using ActiproSoftware.Windows.Controls.Docking;
// using ActiproSoftware.ProductSamples.DockingSamples.Common.ViewModels;
namespace ActiProUtil
{
/// <summary>
/// Provides attached behaviors for <see cref="DockSite"/> that properly initializes/opens windows associated with view-models.
/// </summary>
public static class DockSiteViewModelBehavior
{
#region Dependency Properties
/// <summary>
/// Identifies the <c>IsManaged</c> attached dependency property. This field is read-only.
/// </summary>
/// <value>The identifier for the <c>IsManaged</c> attached dependency property.</value>
public static readonly DependencyProperty IsManagedProperty = DependencyProperty.RegisterAttached("IsManaged",
typeof(bool), typeof(DockSiteViewModelBehavior), new FrameworkPropertyMetadata(false, OnIsManagedPropertyValueChanged));
/// <summary>
/// Identifies the <c>WindowsPendingOpen</c> attached dependency property. This field is read-only.
/// </summary>
/// <value>The identifier for the <c>WindowsPendingOpen</c> attached dependency property.</value>
private static readonly DependencyProperty WindowsPendingOpenProperty = DependencyProperty.RegisterAttached("WindowsPendingOpen",
typeof(IList<DockingWindow>), typeof(DockSiteViewModelBehavior), new FrameworkPropertyMetadata(null));
public static readonly DependencyProperty ActiveModelProperty = DependencyProperty.RegisterAttached("ActiveModel",
typeof (object), typeof (DockSiteViewModelBehavior)); //, new FrameworkPropertyMetadata(null, OnActiveModelChanged));
//public static readonly RoutedEvent OnModelActiveChnagedEvent = EventManager.RegisterRoutedEvent(
// "OnModelActiveChanged", RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (DockSiteViewModelBehavior));
#endregion // Dependency Properties
/////////////////////////////////////////////////////////////////////////////////////////////////////
// NON-PUBLIC PROCEDURES
/////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Gets the first <see cref="ToolWindow"/> associated with the specified dock group.
/// </summary>
/// <param name="dockSite">The dock site to search.</param>
/// <param name="dockGroup">The dock group.</param>
/// <returns>
/// A <see cref="ToolWindow"/>; otherwise, <see langword="null"/>.
/// </returns>
private static ToolWindow GetToolWindow(DockSite dockSite, string dockGroup)
{
if (dockSite != null && !string.IsNullOrEmpty(dockGroup))
{
foreach (ToolWindow toolWindow in dockSite.ToolWindows)
{
ToolItemViewModel toolItemViewModel = toolWindow.DataContext as ToolItemViewModel;
if (toolItemViewModel != null && toolItemViewModel.DockGroup == dockGroup)
return toolWindow;
}
}
return null;
}
/// <summary>
/// Handles the <c>Loaded</c> event of the <c>DockSite</c> control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
private static void OnDockSiteLoaded(object sender, RoutedEventArgs e)
{
DockSite dockSite = sender as DockSite;
if (dockSite == null)
return;
// Open any windows that were waiting for the DockSite to be loaded
IList<DockingWindow> windowsPendingOpen = dockSite.GetValue(WindowsPendingOpenProperty) as IList<DockingWindow>;
dockSite.ClearValue(WindowsPendingOpenProperty);
if (windowsPendingOpen != null && windowsPendingOpen.Count != 0)
{
foreach (DockingWindow dockingWindow in windowsPendingOpen)
OpenDockingWindow(dockSite, dockingWindow);
}
}
/// <summary>
/// Handles the <c>WindowRegistered</c> event of the <c>DockSite</c> control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="DockingWindowEventArgs"/> instance containing the event data.</param>
private static void OnDockSiteWindowRegistered(object sender, DockingWindowEventArgs e)
{
DockSite dockSite = sender as DockSite;
if (dockSite == null)
return;
// Ensure the DockingWindow exists and is generated for an item
DockingWindow dockingWindow = e.Window;
if (dockingWindow == null || !dockingWindow.IsContainerForItem)
return;
// Pass down the name, if any as this cannot be done via a Style
if (string.IsNullOrEmpty(dockingWindow.Name))
{
ViewModelBase viewModel = dockingWindow.DataContext as ViewModelBase;
if (viewModel != null && !string.IsNullOrEmpty(viewModel.Name))
dockingWindow.Name = viewModel.Name;
}
// Open the DockingWindow, if it's not already open
if (!dockingWindow.IsOpen)
{
if (!dockSite.IsLoaded)
{
// Need to delay the opening until after the DockSite is loaded because it's content will not be loaded
IList<DockingWindow> windowsPendingOpen = dockSite.GetValue(WindowsPendingOpenProperty) as IList<DockingWindow>;
if (windowsPendingOpen == null)
{
windowsPendingOpen = new List<DockingWindow>();
dockSite.SetValue(WindowsPendingOpenProperty, windowsPendingOpen);
}
windowsPendingOpen.Add(dockingWindow);
}
else
{
OpenDockingWindow(dockSite, dockingWindow);
// EO: To fix a bug in event "LastActiveDocument" which does not trig on initial window.
dockSite.Dispatcher.BeginInvoke(new Action(() =>
{
if (dockSite.DocumentWindows.Count == 1)
{
dockingWindow.Activate();
}
}));
}
}
}
/// <summary>
/// Handles the <c>WindowUnregistered</c> event of the <c>DockSite</c> control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="DockingWindowEventArgs"/> instance containing the event data.</param>
private static void OnDockSiteWindowUnregistered(object sender, DockingWindowEventArgs e)
{
DockSite dockSite = sender as DockSite;
if (dockSite == null)
return;
// Ensure the DockingWindow exists and is generated for an item
DockingWindow dockingWindow = e.Window;
if (dockingWindow == null || !dockingWindow.IsContainerForItem)
return;
// Need to remove the window from the list of windows that are waiting to be opened
IList<DockingWindow> windowsPendingOpen = dockSite.GetValue(WindowsPendingOpenProperty) as IList<DockingWindow>;
if (windowsPendingOpen != null)
{
int index = windowsPendingOpen.IndexOf(dockingWindow);
if (index != -1)
windowsPendingOpen.RemoveAt(index);
}
}
/// <summary>
/// Called when <see cref="IsManagedProperty"/> is changed.
/// </summary>
/// <param name="d">The dependency object that was changed.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void OnIsManagedPropertyValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DockSite dockSite = d as DockSite;
if (dockSite == null)
return;
// Add/Remove handlers for various events, which will allow us to open/position generated windows
if ((bool)e.NewValue)
{
dockSite.Loaded += DockSiteViewModelBehavior.OnDockSiteLoaded;
dockSite.WindowRegistered += DockSiteViewModelBehavior.OnDockSiteWindowRegistered;
dockSite.WindowUnregistered += DockSiteViewModelBehavior.OnDockSiteWindowUnregistered;
// EO 2014-12-10, Added next line
dockSite.LastActiveDocumentChanged += dockSite_LastActiveDocumentChanged;
}
else
{
dockSite.Loaded -= DockSiteViewModelBehavior.OnDockSiteLoaded;
dockSite.WindowRegistered -= DockSiteViewModelBehavior.OnDockSiteWindowRegistered;
dockSite.WindowUnregistered -= DockSiteViewModelBehavior.OnDockSiteWindowUnregistered;
// EO 2014-12-10, Added next line
dockSite.LastActiveDocumentChanged -= dockSite_LastActiveDocumentChanged;
}
}
/// <summary>
/// Called when <see cref="IsManagedProperty"/> is changed.
/// </summary>
/// <param name="d">The dependency object that was changed.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void OnActiveModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DockSite dockSite = d as DockSite;
if (dockSite == null)
return;
OnActiveModelChanged(d, e);
}
/// <summary>
/// EO 2014-12-10, Added next event handler
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void dockSite_LastActiveDocumentChanged(object sender, DockingWindowPropertyChangedRoutedEventArgs e)
{
var dockSite = sender as DockSite;
if (dockSite != null)
{
if (dockSite.ActiveWindow != null)
{
var obj = dockSite.ActiveWindow.DataContext as object;
if (obj != null)
{
dockSite.SetValue(ActiveModelProperty, obj);
return;
}
}
dockSite.SetValue(ActiveModelProperty, null);
}
}
/// <summary>
/// Opens the specified docking window.
/// </summary>
/// <param name="dockSite">The dock site that owns the docking window.</param>
/// <param name="dockingWindow">The docking window to open.</param>
private static void OpenDockingWindow(DockSite dockSite, DockingWindow dockingWindow)
{
if (!dockingWindow.IsOpen)
{
if (dockingWindow is DocumentWindow)
dockingWindow.Open();
else
{
ToolWindow toolWindow = dockingWindow as ToolWindow;
ToolItemViewModel toolItemViewModel = dockingWindow.DataContext as ToolItemViewModel;
if (toolWindow != null && toolItemViewModel != null)
{
// Look for a ToolWindow within the same group, if found then dock to that group, otherwise either dock or auto-hide the window
ToolWindow targetToolWindow = GetToolWindow(dockSite, toolItemViewModel.DockGroup);
if (targetToolWindow != null && targetToolWindow != toolWindow)
toolWindow.Dock(targetToolWindow, Direction.Content);
else if (toolItemViewModel.IsInitiallyAutoHidden)
toolWindow.AutoHide(toolItemViewModel.DefaultDock);
else
toolWindow.Dock(dockSite, toolItemViewModel.DefaultDock);
}
else
{
dockingWindow.Open();
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// PUBLIC PROCEDURES
/////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Gets the value of the <see cref="IsManagedProperty"/> attached property for a specified <see cref="DockSite"/>.
/// </summary>
/// <param name="obj">The object to which the attached property is retrieved.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="DockSite"/> is being managed; otherwise <c>false</c>.
/// </returns>
public static bool GetIsManaged(DockSite obj)
{
if (null == obj) throw new ArgumentNullException("obj");
return (bool)obj.GetValue(DockSiteViewModelBehavior.IsManagedProperty);
}
/// <summary>
/// Sets the value of the <see cref="IsManagedProperty"/> attached property to a specified <see cref="DockSite"/>.
/// </summary>
/// <param name="obj">The object to which the attached property is written.</param>
/// <param name="value">
/// A value indicating whether the specified <see cref="DockSite"/> is being managed.
/// </param>
public static void SetIsManaged(DockSite obj, bool value)
{
if (null == obj) throw new ArgumentNullException("obj");
obj.SetValue(DockSiteViewModelBehavior.IsManagedProperty, value);
}
}
}
XAML:
<docking:DockSite x:Name="DockSiteMain"
CanToolWindowsBecomeDocuments="False"
CanDocumentWindowsRaft="True"
ItemContainerRetentionMode="Wrapped"
actiProUtil:DockSiteViewModelBehavior.IsManaged="true"
DocumentItemsSource="{Binding UserControlSvgEdits}"
DocumentItemContainerStyle="{StaticResource DocumentItemStyle}"
>
Upvotes: 0
Views: 2491
Reputation: 11754
I changed my behavior to the newer behavior architecture ("blend" style defined in System.Windows.Interactivity). Then I only added a regular event into my behavior which worked as expected.
There is code: behavior and its call in xaml:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Threading;
using ActiproSoftware.Windows.Controls.Docking;
// using ActiproSoftware.ProductSamples.DockingSamples.Common.ViewModels;
namespace ActiProUtil
{
public delegate void ActiveModelChangedHandler(object sender, DependencyPropertyChangedEventArgs eventArgs);
/// <summary>
/// EO: Provides attached behaviors for <see cref="DockSite"/> that properly initializes/opens windows associated
/// with view-models. Proper behavior depends on the Model staying the DataContext of the view
/// </summary>
public class DockSiteViewModelBehavior : Behavior<DockSite>
{
// ******************************************************************
/// <summary>
/// Identifies the <c>IsManaged</c> attached dependency property. This field is read-only.
/// </summary>
/// <value>The identifier for the <c>IsManaged</c> attached dependency property.</value>
public static readonly DependencyProperty IsManagedProperty = DependencyProperty.Register("IsManaged",
typeof(bool), typeof(DockSiteViewModelBehavior), new FrameworkPropertyMetadata(false, OnIsManagedPropertyValueChanged));
/// <summary>
/// Identifies the <c>WindowsPendingOpen</c> attached dependency property. This field is read-only.
/// </summary>
/// <value>The identifier for the <c>WindowsPendingOpen</c> attached dependency property.</value>
private static readonly DependencyProperty WindowsPendingOpenProperty = DependencyProperty.Register("WindowsPendingOpen",
typeof(IList<DockingWindow>), typeof(DockSiteViewModelBehavior), new FrameworkPropertyMetadata(null));
public static readonly DependencyProperty ActiveModelProperty = DependencyProperty.Register("ActiveModel",
typeof (object), typeof (DockSiteViewModelBehavior), new FrameworkPropertyMetadata(null, OnActiveModelChanged));
//public static readonly RoutedEvent OnModelActiveChnagedEvent = EventManager.RegisterRoutedEvent(
// "OnModelActiveChanged", RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (DockSiteViewModelBehavior));
public static readonly DependencyProperty ModelsSourceProperty = DependencyProperty.Register("ModelsSource",
typeof(object), typeof(DockSiteViewModelBehavior), new FrameworkPropertyMetadata(null, OnDocumentSourceChanged));
public event ActiveModelChangedHandler ActiveModelChanged;
// ******************************************************************
private DockSite _dockSite = null;
// ******************************************************************
private DockSite DockSite
{
get
{
if (_dockSite == null)
{
_dockSite = AssociatedObject;
}
return _dockSite;
}
}
// ******************************************************************
/// <summary>
/// Gets the first <see cref="ToolWindow"/> associated with the specified dock group.
/// </summary>
/// <param name="dockSite">The dock site to search.</param>
/// <param name="dockGroup">The dock group.</param>
/// <returns>
/// A <see cref="ToolWindow"/>; otherwise, <see langword="null"/>.
/// </returns>
private static ToolWindow GetToolWindow(DockSite dockSite, string dockGroup)
{
if (dockSite != null && !string.IsNullOrEmpty(dockGroup))
{
foreach (ToolWindow toolWindow in dockSite.ToolWindows)
{
ToolItemViewModel toolItemViewModel = toolWindow.DataContext as ToolItemViewModel;
if (toolItemViewModel != null && toolItemViewModel.DockGroup == dockGroup)
return toolWindow;
}
}
return null;
}
// ******************************************************************
/// <summary>
/// Handles the <c>Loaded</c> event of the <c>DockSite</c> control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
private void OnDockSiteLoaded(object sender, RoutedEventArgs e)
{
// Open any windows that were waiting for the DockSite to be loaded
IList<DockingWindow> windowsPendingOpen = DockSite.GetValue(WindowsPendingOpenProperty) as IList<DockingWindow>;
DockSite.ClearValue(WindowsPendingOpenProperty);
if (windowsPendingOpen != null && windowsPendingOpen.Count != 0)
{
foreach (DockingWindow dockingWindow in windowsPendingOpen)
OpenDockingWindow(DockSite, dockingWindow);
}
}
// ******************************************************************
/// <summary>
/// Handles the <c>WindowRegistered</c> event of the <c>DockSite</c> control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="DockingWindowEventArgs"/> instance containing the event data.</param>
private void OnDockSiteWindowRegistered(object sender, DockingWindowEventArgs e)
{
var dockSite = sender as DockSite;
if (dockSite == null)
throw new ArgumentException("DockSiteViewModelBehavior is dedicated to actipro DockSite");
// Ensure the DockingWindow exists and is generated for an item
DockingWindow dockingWindow = e.Window;
if (dockingWindow == null || !dockingWindow.IsContainerForItem)
return;
// Pass down the name, if any as this cannot be done via a Style
if (string.IsNullOrEmpty(dockingWindow.Name))
{
ViewModelBase viewModel = dockingWindow.DataContext as ViewModelBase;
if (viewModel != null && !string.IsNullOrEmpty(viewModel.Name))
dockingWindow.Name = viewModel.Name;
}
// Open the DockingWindow, if it's not already open
if (!dockingWindow.IsOpen)
{
if (!dockSite.IsLoaded)
{
// Need to delay the opening until after the DockSite is loaded because it's content will not be loaded
IList<DockingWindow> windowsPendingOpen = dockSite.GetValue(WindowsPendingOpenProperty) as IList<DockingWindow>;
if (windowsPendingOpen == null)
{
windowsPendingOpen = new List<DockingWindow>();
dockSite.SetValue(WindowsPendingOpenProperty, windowsPendingOpen);
}
windowsPendingOpen.Add(dockingWindow);
}
else
{
OpenDockingWindow(dockSite, dockingWindow);
// EO: To fix a bug in event "LastActiveDocument" which does not trig on initial window.
dockSite.Dispatcher.BeginInvoke(new Action(() =>
{
if (dockSite.DocumentWindows.Count == 1)
{
dockingWindow.Activate();
}
}), DispatcherPriority.ContextIdle);
}
}
}
// ******************************************************************
private void EnsureDockingWindowAssociatedModelIsClose(DockingWindow dockingWindow)
{
if (dockingWindow != null)
{
object model = GetDockinWindowDataContext(dockingWindow);
if (model != null)
{
var iList = ModelsSource as IList;
if (iList != null)
{
iList.Remove(model);
}
}
}
}
// ******************************************************************
/// <summary>
/// Handles the <c>WindowUnregistered</c> event of the <c>DockSite</c> control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="DockingWindowEventArgs"/> instance containing the event data.</param>
private void OnDockSiteWindowUnregistered(object sender, DockingWindowEventArgs e)
{
DockSite dockSite = sender as DockSite;
if (dockSite == null)
return;
// Ensure the DockingWindow exists and is generated for an item
DockingWindow dockingWindow = e.Window;
if (dockingWindow == null || !dockingWindow.IsContainerForItem)
return;
// Need to remove the window from the list of windows that are waiting to be opened
IList<DockingWindow> windowsPendingOpen = dockSite.GetValue(WindowsPendingOpenProperty) as IList<DockingWindow>;
if (windowsPendingOpen != null)
{
int index = windowsPendingOpen.IndexOf(dockingWindow);
if (index != -1)
{
EnsureDockingWindowAssociatedModelIsClose(dockingWindow);
windowsPendingOpen.RemoveAt(index);
}
}
}
// ******************************************************************
/// <summary>
/// Called when <see cref="IsManagedProperty"/> is changed.
/// </summary>
/// <param name="d">The dependency object that was changed.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void OnIsManagedPropertyValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var dockSiteViewModelBehavior = d as DockSiteViewModelBehavior;
if (dockSiteViewModelBehavior == null)
{
return;
}
}
// ******************************************************************
protected override void OnAttached()
{
base.OnAttached();
var dockSite = DockSite;
// Add/Remove handlers for various events, which will allow us to open/position generated windows
if (IsManaged)
{
dockSite.Loaded += OnDockSiteLoaded;
dockSite.WindowRegistered += OnDockSiteWindowRegistered;
dockSite.WindowUnregistered += OnDockSiteWindowUnregistered;
// EO 2014-12-10, Added next lines
dockSite.WindowClosing += dockSite_WindowClosing;
dockSite.LastActiveDocumentChanged += DockSiteOnLastActiveDocumentChanged;
}
else
{
dockSite.Loaded -= OnDockSiteLoaded;
dockSite.WindowRegistered -= OnDockSiteWindowRegistered;
dockSite.WindowUnregistered -= OnDockSiteWindowUnregistered;
// EO 2014-12-10, Added next lines
dockSite.WindowClosing -= dockSite_WindowClosing;
dockSite.LastActiveDocumentChanged -= DockSiteOnLastActiveDocumentChanged;
}
}
// ******************************************************************
void dockSite_WindowClosing(object sender, DockingWindowEventArgs e)
{
EnsureDockingWindowAssociatedModelIsClose(e.Window);
}
// ******************************************************************
private void DockSiteOnLastActiveDocumentChanged(object sender, DockingWindowPropertyChangedRoutedEventArgs dockingWindowPropertyChangedRoutedEventArgs)
{
var dockSite = sender as DockSite;
if (dockSite != null)
{
if (dockSite.ActiveWindow != null)
{
var frameWorkElement = dockSite.ActiveWindow.Content as FrameworkElement;
if (frameWorkElement != null)
{
ActiveModel = frameWorkElement.DataContext;
return;
}
}
ActiveModel = null;
}
}
// ******************************************************************
/// <summary>
/// Called when <see cref="IsManagedProperty"/> is changed.
/// </summary>
/// <param name="d">The dependency object that was changed.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void OnDocumentSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var behavior = d as DockSiteViewModelBehavior;
if (behavior == null)
{
throw new ArgumentNullException();
}
var obsCollOld = e.OldValue as INotifyCollectionChanged;
if (obsCollOld != null)
{
obsCollOld.CollectionChanged -= behavior.ObjCollCollectionChanged;
}
var obsCollNew = e.NewValue as INotifyCollectionChanged;
if (obsCollNew != null)
{
obsCollNew.CollectionChanged += behavior.ObjCollCollectionChanged;
}
}
// ******************************************************************
void ObjCollCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// Find the DataTemplate
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (object obj in e.NewItems)
{
// Here th obj Type is the key to the resource, it works but
var key = new System.Windows.DataTemplateKey(obj.GetType());
var dataTemplate = (DataTemplate)DockSite.FindResource(key);
var userControl = dataTemplate.LoadContent() as UserControl;
if (userControl != null)
{
userControl.DataContext = obj;
var documentWindow = new DocumentWindow(DockSite, null, "Title from viemodel", null, userControl);
documentWindow.Description = "viewModel.Description";
// Activate the document
documentWindow.Activate();
}
}
}
}
// ******************************************************************
/// <summary>
/// Called when <see cref="IsManagedProperty"/> is changed.
/// </summary>
/// <param name="d">The dependency object that was changed.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void OnActiveModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var behavior = d as DockSiteViewModelBehavior;
if (behavior == null)
{
return;
}
DockSite dockSite = behavior.AssociatedObject;
bool isAlreadyProperModelOfProperActiveWindow = false;
if (dockSite.ActiveWindow != null)
{
var frameworkElement = dockSite.ActiveWindow.Content as FrameworkElement;
if (frameworkElement != null)
{
if (frameworkElement.DataContext == behavior.ActiveModel)
{
isAlreadyProperModelOfProperActiveWindow = true;
}
}
}
if (!isAlreadyProperModelOfProperActiveWindow)
{
foreach (var docWin in dockSite.DocumentWindows)
{
var frameworkElement = docWin.Content as FrameworkElement;
if (frameworkElement != null)
{
if (frameworkElement.DataContext == behavior.ActiveModel)
{
docWin.Activate();
}
}
}
}
if (behavior.ActiveModelChanged != null)
{
behavior.ActiveModelChanged(behavior, new DependencyPropertyChangedEventArgs(ActiveModelProperty, e.OldValue, e.NewValue));
}
}
// ******************************************************************
/// <summary>
/// Opens the specified docking window.
/// </summary>
/// <param name="dockSite">The dock site that owns the docking window.</param>
/// <param name="dockingWindow">The docking window to open.</param>
private static void OpenDockingWindow(DockSite dockSite, DockingWindow dockingWindow)
{
if (!dockingWindow.IsOpen)
{
if (dockingWindow is DocumentWindow)
dockingWindow.Open();
else
{
ToolWindow toolWindow = dockingWindow as ToolWindow;
ToolItemViewModel toolItemViewModel = dockingWindow.DataContext as ToolItemViewModel;
if (toolWindow != null && toolItemViewModel != null)
{
// Look for a ToolWindow within the same group, if found then dock to that group, otherwise either dock or auto-hide the window
ToolWindow targetToolWindow = GetToolWindow(dockSite, toolItemViewModel.DockGroup);
if (targetToolWindow != null && targetToolWindow != toolWindow)
toolWindow.Dock(targetToolWindow, Direction.Content);
else if (toolItemViewModel.IsInitiallyAutoHidden)
toolWindow.AutoHide(toolItemViewModel.DefaultDock);
else
toolWindow.Dock(dockSite, toolItemViewModel.DefaultDock);
}
else
{
dockingWindow.Open();
}
}
}
}
// ******************************************************************
public bool IsManaged
{
get { return (bool)GetValue(DockSiteViewModelBehavior.IsManagedProperty); }
set { SetValue(DockSiteViewModelBehavior.IsManagedProperty, value); }
}
// ******************************************************************
public object ModelsSource
{
get { return GetValue(ModelsSourceProperty); }
set { SetValue(ModelsSourceProperty, value); }
}
// ******************************************************************
public object ActiveModel
{
get { return GetValue(ActiveModelProperty); }
set { SetValue(ActiveModelProperty, value); }
}
// ******************************************************************
private static object GetDockinWindowDataContext(DockingWindow dockingWindow)
{
object dataContext = null;
if (dockingWindow != null)
{
var frameworkElement = dockingWindow.Content as FrameworkElement;
if (frameworkElement != null)
{
dataContext = frameworkElement.DataContext;
}
}
return dataContext;
}
// ******************************************************************
}
}
This the xaml portion using the behavior:
<docking:DockSite x:Name="DockSiteMain"
CanToolWindowsBecomeDocuments="False"
CanDocumentWindowsRaft="True"
ItemContainerRetentionMode="Wrapped"
>
<i:Interaction.Behaviors>
<actiProUtil:DockSiteViewModelBehavior
IsManaged="true"
ModelsSource = "{Binding UserControlSvgEditModels}"
ActiveModel ="{Binding ActiveModel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ActiveModelChanged="DockSiteViewModelBehaviorOnActiveModelChanged"
>
</actiProUtil:DockSiteViewModelBehavior>
</i:Interaction.Behaviors>
...
Upvotes: 0
Reputation: 3848
In order to add additional events from a behavior, you should use Attached Events. Have a look: Attached Events Overview
The code should be something like that:
public static class DockSiteViewModelBehavior
{
...
public static readonly RoutedEvent OnModelActiveChnagedEvent = EventManager.RegisterRoutedEvent(
"OnModelActiveChanged", RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof (DockSiteViewModelBehavior));
public static void AddOnModelActiveChangedHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement uie = d as UIElement;
if (uie != null)
{
uie.AddHandler(OnModelActiveChnagedEvent, handler);
}
}
public static void RemoveOnModelActiveChangedHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement uie = d as UIElement;
if (uie != null)
{
uie.RemoveHandler(OnModelActiveChnagedEvent, handler);
}
}
...
private static void OnActiveModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DockSite dockSite = d as DockSite;
if (dockSite == null)
return;
dockSite.RaiseEvent(new RoutedEventArgs(OnModelActiveChnagedEvent, dockSite));
}
}
Upvotes: 2