diff --git a/source/Components/AvalonDock/Commands/IExecuteWithObject.cs b/source/Components/AvalonDock/Commands/IExecuteWithObject.cs
new file mode 100644
index 00000000..3a081906
--- /dev/null
+++ b/source/Components/AvalonDock/Commands/IExecuteWithObject.cs
@@ -0,0 +1,38 @@
+namespace AvalonDock.Commands
+{
+ ///
+ /// Interface IExecuteWithObject
+ ///
+ internal interface IExecuteWithObject
+ {
+ #region Public Properties
+
+ ///
+ /// The target of the WeakAction.
+ ///
+ /// The target.
+ object Target
+ {
+ get;
+ }
+
+ #endregion Public Properties
+
+ #region Public Methods
+
+ ///
+ /// Executes an action.
+ ///
+ /// A parameter passed as an object,
+ /// to be casted to the appropriate type.
+ void ExecuteWithObject(object parameter);
+
+ ///
+ /// Deletes all references, which notifies the cleanup method
+ /// that this entry must be deleted.
+ ///
+ void MarkForDeletion();
+
+ #endregion Public Methods
+ }
+}
\ No newline at end of file
diff --git a/source/Components/AvalonDock/Commands/IExecuteWithObjectAndResult.cs b/source/Components/AvalonDock/Commands/IExecuteWithObjectAndResult.cs
new file mode 100644
index 00000000..5590b270
--- /dev/null
+++ b/source/Components/AvalonDock/Commands/IExecuteWithObjectAndResult.cs
@@ -0,0 +1,20 @@
+namespace AvalonDock.Commands
+{
+ ///
+ /// Interface IExecuteWithObjectAndResult
+ ///
+ internal interface IExecuteWithObjectAndResult
+ {
+ #region Public Methods
+
+ ///
+ /// Executes a Func and returns the result.
+ ///
+ /// A parameter passed as an object,
+ /// to be casted to the appropriate type.
+ /// The result of the operation.
+ object ExecuteWithObject(object parameter);
+
+ #endregion Public Methods
+ }
+}
\ No newline at end of file
diff --git a/source/Components/AvalonDock/Commands/RelayCommand.cs b/source/Components/AvalonDock/Commands/RelayCommand.cs
index f63c59c9..78a64e55 100644
--- a/source/Components/AvalonDock/Commands/RelayCommand.cs
+++ b/source/Components/AvalonDock/Commands/RelayCommand.cs
@@ -8,67 +8,199 @@ This program is provided to you under the terms of the Microsoft Public
************************************************************************/
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Windows.Input;
namespace AvalonDock.Commands
{
- ///
- ///
- /// A command whose sole purpose is to relay its functionality to other
- /// objects by invoking delegates.
- /// The default return value for the method is true .
- ///
- /// Source:
- ///
- ///
- internal class RelayCommand : ICommand
- {
- #region fields
- private readonly Action _execute;
- private readonly Predicate _canExecute;
- #endregion fields
-
- #region Constructors
-
- ///
- /// Class constructor from parameter.
- ///
- /// The action to execute when the command is activated.
- public RelayCommand(Action execute) : this(execute, null)
- {
- }
-
- ///
- /// Class constructor from parameter plus
- /// canExecute predicate to decide whether command should currently
- /// be available or not.
- ///
- /// The action to execute when the command is activated.
- /// The predicate to determine if this command can be executed.
- public RelayCommand(Action execute, Predicate canExecute)
- {
- _execute = execute ?? throw new ArgumentNullException(nameof(execute));
- _canExecute = canExecute;
- }
-
- #endregion Constructors
-
- #region ICommand Members
-
- ///
- public event EventHandler CanExecuteChanged
- {
- add => CommandManager.RequerySuggested += value;
- remove => CommandManager.RequerySuggested -= value;
- }
-
- ///
- /// Returns true , if no predicate is set for the check.
- public bool CanExecute(object parameter) => _canExecute?.Invoke(parameter) ?? true;
-
- ///
- public void Execute(object parameter) => _execute(parameter);
-
- #endregion ICommand Members
- }
-}
+ ///
+ ///
+ /// A command whose sole purpose is to relay its functionality to other
+ /// objects by invoking delegates.
+ /// The default return value for the method is true .
+ ///
+ /// Source:
+ ///
+ ///
+ ///
+ /// Class RelayCommand.
+ ///
+ ///
+ ///
+ internal class RelayCommand : ICommand
+ {
+ #region Private Fields
+
+ ///
+ /// The can execute
+ ///
+ private readonly WeakFunc _canExecute;
+
+ ///
+ /// The execute
+ ///
+ private readonly WeakAction _execute;
+
+ #endregion Private Fields
+
+ #region Public Constructors
+
+ ///
+ /// Initializes a new instance of the RelayCommand class that
+ /// can always execute.
+ ///
+ /// The execution logic. IMPORTANT: Note that closures are not supported at the moment
+ /// due to the use of WeakActions (see http://stackoverflow.com/questions/25730530/).
+ /// If the execute argument is null.
+ public RelayCommand(Action execute)
+ : this(execute, null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the RelayCommand class.
+ ///
+ /// The execution logic. IMPORTANT: Note that closures are not supported at the moment
+ /// due to the use of WeakActions (see http://stackoverflow.com/questions/25730530/).
+ /// The execution status logic. IMPORTANT: Note that closures are not supported at the moment
+ /// due to the use of WeakActions (see http://stackoverflow.com/questions/25730530/).
+ /// If the execute argument is null.
+ public RelayCommand(Action execute, Func canExecute)
+ {
+ if (execute == null)
+ {
+ throw new ArgumentNullException("execute");
+ }
+
+ _execute = new WeakAction(execute);
+
+ if (canExecute != null)
+ {
+ _canExecute = new WeakFunc(canExecute);
+ }
+ }
+
+ #endregion Public Constructors
+
+ #region Public Events
+
+ ///
+ /// Occurs when changes occur that affect whether the command should execute.
+ ///
+ public event EventHandler CanExecuteChanged
+ {
+ add
+ {
+ if (_canExecute != null)
+ {
+ CommandManager.RequerySuggested += value;
+ }
+ }
+
+ remove
+ {
+ if (_canExecute != null)
+ {
+ CommandManager.RequerySuggested -= value;
+ }
+ }
+ }
+
+ #endregion Public Events
+
+ #region Public Methods
+
+ ///
+ /// Defines the method that determines whether the command can execute in its current state.
+ ///
+ /// Data used by the command. If the command does not require data
+ /// to be passed, this object can be set to a null reference
+ /// true if this command can be executed; otherwise, false.
+ public bool CanExecute(object parameter)
+ {
+ if (_canExecute == null)
+ {
+ return true;
+ }
+
+ if (_canExecute.IsStatic || _canExecute.IsAlive)
+ {
+ if (parameter == null && typeof(T).IsValueType)
+ {
+ return _canExecute.Execute(default);
+ }
+
+ if (parameter == null || parameter is T)
+ {
+ return (_canExecute.Execute((T)parameter));
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// Defines the method to be called when the command is invoked.
+ ///
+ /// Data used by the command. If the command does not require data
+ /// to be passed, this object can be set to a null reference
+ public virtual void Execute(object parameter)
+ {
+ var val = parameter;
+
+ if (parameter != null
+ && parameter.GetType() != typeof(T))
+ {
+ if (typeof(T).IsEnum)
+ {
+ val = Enum.Parse(typeof(T), parameter.ToString());
+ }
+ else if (parameter is IConvertible)
+ {
+ val = Convert.ChangeType(parameter, typeof(T), null);
+ }
+ }
+
+ if (CanExecute(val)
+ && _execute != null
+ && (_execute.IsStatic || _execute.IsAlive))
+ {
+ if (val == null)
+ {
+ if (typeof(T).IsValueType)
+ {
+ _execute.Execute(default);
+ }
+ else
+ {
+ // ReSharper disable ExpressionIsAlwaysNull
+ _execute.Execute((T)val);
+ // ReSharper restore ExpressionIsAlwaysNull
+ }
+ }
+ else
+ {
+ _execute.Execute((T)val);
+ }
+ }
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ [SuppressMessage(
+ "Microsoft.Performance",
+ "CA1822:MarkMembersAsStatic",
+ Justification = "The this keyword is used in the Silverlight version")]
+ [SuppressMessage(
+ "Microsoft.Design",
+ "CA1030:UseEventsWhereAppropriate",
+ Justification = "This cannot be an event")]
+ public void RaiseCanExecuteChanged()
+ {
+ CommandManager.InvalidateRequerySuggested();
+ }
+
+ #endregion Public Methods
+ }
+}
\ No newline at end of file
diff --git a/source/Components/AvalonDock/Commands/WeakAction.cs b/source/Components/AvalonDock/Commands/WeakAction.cs
new file mode 100644
index 00000000..de8ccca7
--- /dev/null
+++ b/source/Components/AvalonDock/Commands/WeakAction.cs
@@ -0,0 +1,284 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Reflection;
+
+namespace AvalonDock.Commands
+{
+ ///
+ /// Class WeakAction.
+ ///
+ internal class WeakAction
+ {
+ #region Private Fields
+
+ ///
+ /// The static action
+ ///
+ private Action _staticAction;
+
+ #endregion Private Fields
+
+ #region Public Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The action that will be associated to this instance.
+ public WeakAction(Action action)
+ : this(action?.Target, action)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The action's owner.
+ /// The action that will be associated to this instance.
+ [SuppressMessage(
+ "Microsoft.Design",
+ "CA1062:Validate arguments of public methods",
+ MessageId = "1",
+ Justification = "Method should fail with an exception if action is null.")]
+ public WeakAction(object target, Action action)
+ {
+ if (action.Method.IsStatic)
+ {
+ _staticAction = action;
+
+ if (target != null)
+ {
+ // Keep a reference to the target to control the
+ // WeakAction's lifetime.
+ Reference = new WeakReference(target);
+ }
+
+ return;
+ }
+ Method = action.Method;
+ ActionReference = new WeakReference(action.Target);
+ Reference = new WeakReference(target);
+ }
+
+ #endregion Public Constructors
+
+ #region Protected Constructors
+
+ ///
+ /// Initializes an empty instance of the class.
+ ///
+ protected WeakAction()
+ {
+ }
+
+ #endregion Protected Constructors
+
+ #region Public Properties
+
+ ///
+ /// Gets a value indicating whether the Action's owner is still alive, or if it was collected
+ /// by the Garbage Collector already.
+ ///
+ /// true 如果 this instance is alive; 否则, false .
+ public virtual bool IsAlive
+ {
+ get
+ {
+ if (_staticAction == null
+ && Reference == null)
+ {
+ return false;
+ }
+
+ if (_staticAction != null)
+ {
+ if (Reference != null)
+ {
+ return Reference.IsAlive;
+ }
+
+ return true;
+ }
+
+ return Reference.IsAlive;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the WeakAction is static or not.
+ ///
+ /// true 如果 this instance is static; 否则, false .
+ public bool IsStatic
+ {
+ get
+ {
+#if SILVERLIGHT
+ return (_action != null && _action.Target == null)
+ || _staticAction != null;
+#else
+ return _staticAction != null;
+#endif
+ }
+ }
+
+ ///
+ /// Gets the name of the method that this WeakAction represents.
+ ///
+ /// The name of the method.
+ public virtual string MethodName
+ {
+ get
+ {
+ if (_staticAction != null)
+ {
+ return _staticAction.Method.Name;
+ }
+ return Method.Name;
+ }
+ }
+
+ ///
+ /// Gets the Action's owner. This object is stored as a
+ /// .
+ ///
+ /// The target.
+ public object Target
+ {
+ get
+ {
+ if (Reference == null)
+ {
+ return null;
+ }
+
+ return Reference.Target;
+ }
+ }
+
+ #endregion Public Properties
+
+ #region Protected Properties
+
+ ///
+ /// Gets or sets a WeakReference to this WeakAction's action's target.
+ /// This is not necessarily the same as
+ /// , for example if the
+ /// method is anonymous.
+ ///
+ /// The action reference.
+ protected WeakReference ActionReference
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// The target of the weak reference.
+ ///
+ /// The action target.
+ protected object ActionTarget
+ {
+ get
+ {
+ if (ActionReference == null)
+ {
+ return null;
+ }
+
+ return ActionReference.Target;
+ }
+ }
+
+ ///
+ /// Gets or sets the corresponding to this WeakAction's
+ /// method passed in the constructor.
+ ///
+ /// The method.
+ protected MethodInfo Method
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Gets or sets a WeakReference to the target passed when constructing
+ /// the WeakAction. This is not necessarily the same as
+ /// , for example if the
+ /// method is anonymous.
+ ///
+ /// The reference.
+ protected WeakReference Reference
+ {
+ get;
+ set;
+ }
+
+ #endregion Protected Properties
+
+ #region Public Methods
+
+ ///
+ /// Executes the action. This only happens if the action's owner
+ /// is still alive.
+ ///
+ public void Execute(object param = null)
+ {
+ if (_staticAction != null)
+ {
+ _staticAction();
+ return;
+ }
+
+ var actionTarget = ActionTarget;
+
+ if (IsAlive)
+ {
+ if (Method != null
+ && ActionReference != null
+ && actionTarget != null)
+ {
+ var paras = Method.GetParameters().Count();
+ try
+ {
+ if (paras > 0)
+ {
+ Method.Invoke(actionTarget, new object[] { param });
+ }
+ else
+ {
+ Method.Invoke(actionTarget, null);
+ }
+ }
+ catch { }
+ // ReSharper disable RedundantJumpStatement
+ return;
+ // ReSharper restore RedundantJumpStatement
+ }
+
+#if SILVERLIGHT
+ if (_action != null)
+ {
+ _action();
+ }
+#endif
+ }
+ }
+
+ ///
+ /// Sets the reference that this instance stores to null.
+ ///
+ public void MarkForDeletion()
+ {
+ Reference = null;
+ ActionReference = null;
+ Method = null;
+ _staticAction = null;
+
+#if SILVERLIGHT
+ _action = null;
+#endif
+ }
+
+ #endregion Public Methods
+ }
+}
\ No newline at end of file
diff --git a/source/Components/AvalonDock/Commands/WeakActionGeneric.cs b/source/Components/AvalonDock/Commands/WeakActionGeneric.cs
new file mode 100644
index 00000000..f80574d8
--- /dev/null
+++ b/source/Components/AvalonDock/Commands/WeakActionGeneric.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace AvalonDock.Commands
+{
+ internal class WeakAction : WeakAction, IExecuteWithObject
+ {
+ #region Private Fields
+
+ private Action _staticAction;
+
+ #endregion Private Fields
+
+ #region Public Constructors
+
+ ///
+ /// Initializes a new instance of the WeakAction class.
+ ///
+ /// The action that will be associated to this instance.
+ public WeakAction(Action action)
+ : this(action?.Target, action)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the WeakAction class.
+ ///
+ /// The action's owner.
+ /// The action that will be associated to this instance.
+ [SuppressMessage(
+ "Microsoft.Design",
+ "CA1062:Validate arguments of public methods",
+ MessageId = "1",
+ Justification = "Method should fail with an exception if action is null.")]
+ public WeakAction(object target, Action action)
+ {
+ if (action.Method.IsStatic)
+ {
+ _staticAction = action;
+
+ if (target != null)
+ {
+ // Keep a reference to the target to control the
+ // WeakAction's lifetime.
+ Reference = new WeakReference(target);
+ }
+
+ return;
+ }
+ Method = action.Method;
+ ActionReference = new WeakReference(action.Target);
+ Reference = new WeakReference(target);
+ }
+
+ #endregion Public Constructors
+
+ #region Public Properties
+
+ ///
+ /// Gets a value indicating whether the Action's owner is still alive, or if it was collected
+ /// by the Garbage Collector already.
+ ///
+ public override bool IsAlive
+ {
+ get
+ {
+ if (_staticAction == null
+ && Reference == null)
+ {
+ return false;
+ }
+
+ if (_staticAction != null)
+ {
+ if (Reference != null)
+ {
+ return Reference.IsAlive;
+ }
+
+ return true;
+ }
+
+ return Reference.IsAlive;
+ }
+ }
+
+ ///
+ /// Gets the name of the method that this WeakAction represents.
+ ///
+ public override string MethodName
+ {
+ get
+ {
+ if (_staticAction != null)
+ {
+ return _staticAction.Method.Name;
+ }
+ return Method.Name;
+ }
+ }
+
+ #endregion Public Properties
+
+ #region Public Methods
+
+ ///
+ /// Executes the action. This only happens if the action's owner
+ /// is still alive. The action's parameter is set to default(T).
+ ///
+ public void Execute()
+ {
+ Execute(default);
+ }
+
+ ///
+ /// Executes the action. This only happens if the action's owner
+ /// is still alive.
+ ///
+ /// A parameter to be passed to the action.
+ public void Execute(T parameter)
+ {
+ if (_staticAction != null)
+ {
+ _staticAction(parameter);
+ return;
+ }
+
+ var actionTarget = ActionTarget;
+
+ if (IsAlive)
+ {
+ if (Method != null
+ && ActionReference != null
+ && actionTarget != null)
+ {
+ try
+ {
+ Method.Invoke(
+ actionTarget,
+ new object[]
+ {
+ parameter
+ });
+ }
+ catch { }
+ }
+ }
+ }
+
+ ///
+ /// Executes the action with a parameter of type object. This parameter
+ /// will be casted to T. This method implements
+ /// and can be useful if you store multiple WeakAction{T} instances but don't know in advance
+ /// what type T represents.
+ ///
+ /// The parameter that will be passed to the action after
+ /// being casted to T.
+ public void ExecuteWithObject(object parameter)
+ {
+ var parameterCasted = (T)parameter;
+ Execute(parameterCasted);
+ }
+
+ ///
+ /// Sets all the actions that this WeakAction contains to null,
+ /// which is a signal for containing objects that this WeakAction
+ /// should be deleted.
+ ///
+ public new void MarkForDeletion()
+ {
+ _staticAction = null;
+ base.MarkForDeletion();
+ }
+
+ #endregion Public Methods
+ }
+}
\ No newline at end of file
diff --git a/source/Components/AvalonDock/Commands/WeakFunc.cs b/source/Components/AvalonDock/Commands/WeakFunc.cs
new file mode 100644
index 00000000..188b09ef
--- /dev/null
+++ b/source/Components/AvalonDock/Commands/WeakFunc.cs
@@ -0,0 +1,258 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+
+namespace AvalonDock.Commands
+{
+ ///
+ /// Class WeakFunc.
+ ///
+ /// The type of the t result.
+ internal class WeakFunc
+ {
+ #region Private Fields
+
+ ///
+ /// The static function
+ ///
+ private Func _staticFunc;
+
+ #endregion Private Fields
+
+ #region Public Constructors
+
+ ///
+ /// Initializes a new instance of the WeakFunc class.
+ ///
+ /// The Func that will be associated to this instance.
+ public WeakFunc(Func func)
+ : this(func?.Target, func)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the WeakFunc class.
+ ///
+ /// The Func's owner.
+ /// The Func that will be associated to this instance.
+ [SuppressMessage(
+ "Microsoft.Design",
+ "CA1062:Validate arguments of public methods",
+ MessageId = "1",
+ Justification = "Method should fail with an exception if func is null.")]
+ public WeakFunc(object target, Func func)
+ {
+ if (func.Method.IsStatic)
+ {
+ _staticFunc = func;
+
+ if (target != null)
+ {
+ // Keep a reference to the target to control the
+ // WeakAction's lifetime.
+ Reference = new WeakReference(target);
+ }
+
+ return;
+ }
+ Method = func.Method;
+ FuncReference = new WeakReference(func.Target);
+ Reference = new WeakReference(target);
+ }
+
+ #endregion Public Constructors
+
+ #region Protected Constructors
+
+ ///
+ /// Initializes an empty instance of the WeakFunc class.
+ ///
+ protected WeakFunc()
+ {
+ }
+
+ #endregion Protected Constructors
+
+ #region Public Properties
+
+ ///
+ /// Gets a value indicating whether the Func's owner is still alive, or if it was collected
+ /// by the Garbage Collector already.
+ ///
+ /// true 如果 this instance is alive; 否则, false .
+ public virtual bool IsAlive
+ {
+ get
+ {
+ if (_staticFunc == null
+ && Reference == null)
+ {
+ return false;
+ }
+
+ if (_staticFunc != null)
+ {
+ if (Reference != null)
+ {
+ return Reference.IsAlive;
+ }
+
+ return true;
+ }
+
+ return Reference.IsAlive;
+ }
+ }
+
+ ///
+ /// Get a value indicating whether the WeakFunc is static or not.
+ ///
+ /// true 如果 this instance is static; 否则, false .
+ public bool IsStatic
+ {
+ get
+ {
+ return _staticFunc != null;
+ }
+ }
+
+ ///
+ /// Gets the name of the method that this WeakFunc represents.
+ ///
+ /// The name of the method.
+ public virtual string MethodName
+ {
+ get
+ {
+ if (_staticFunc != null)
+ {
+ return _staticFunc.Method.Name;
+ }
+ return Method.Name;
+ }
+ }
+
+ ///
+ /// Gets the Func's owner. This object is stored as a
+ /// .
+ ///
+ /// The target.
+ public object Target
+ {
+ get
+ {
+ if (Reference == null)
+ {
+ return null;
+ }
+
+ return Reference.Target;
+ }
+ }
+
+ #endregion Public Properties
+
+ #region Protected Properties
+
+ ///
+ /// Gets or sets a WeakReference to this WeakFunc's action's target.
+ /// This is not necessarily the same as
+ /// , for example if the
+ /// method is anonymous.
+ ///
+ /// The function reference.
+ protected WeakReference FuncReference
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Gets the owner of the Func that was passed as parameter.
+ /// This is not necessarily the same as
+ /// , for example if the
+ /// method is anonymous.
+ ///
+ /// The function target.
+ protected object FuncTarget
+ {
+ get
+ {
+ if (FuncReference == null)
+ {
+ return null;
+ }
+
+ return FuncReference.Target;
+ }
+ }
+
+ ///
+ /// Gets or sets the corresponding to this WeakFunc's
+ /// method passed in the constructor.
+ ///
+ /// The method.
+ protected MethodInfo Method
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Gets or sets a WeakReference to the target passed when constructing
+ /// the WeakFunc. This is not necessarily the same as
+ /// , for example if the
+ /// method is anonymous.
+ ///
+ /// The reference.
+ protected WeakReference Reference
+ {
+ get;
+ set;
+ }
+
+ #endregion Protected Properties
+
+ #region Public Methods
+
+ ///
+ /// Executes the action. This only happens if the Func's owner
+ /// is still alive.
+ ///
+ /// The result of the Func stored as reference.
+ public TResult Execute()
+ {
+ if (_staticFunc != null)
+ {
+ return _staticFunc();
+ }
+
+ var funcTarget = FuncTarget;
+
+ if (IsAlive)
+ {
+ if (Method != null
+ && FuncReference != null
+ && funcTarget != null)
+ {
+ return (TResult)Method.Invoke(funcTarget, null);
+ }
+ }
+
+ return default;
+ }
+
+ ///
+ /// Sets the reference that this instance stores to null.
+ ///
+ public void MarkForDeletion()
+ {
+ Reference = null;
+ FuncReference = null;
+ Method = null;
+ _staticFunc = null;
+ }
+
+ #endregion Public Methods
+ }
+}
\ No newline at end of file
diff --git a/source/Components/AvalonDock/Commands/WeakFuncGeneric.cs b/source/Components/AvalonDock/Commands/WeakFuncGeneric.cs
new file mode 100644
index 00000000..0bc9e055
--- /dev/null
+++ b/source/Components/AvalonDock/Commands/WeakFuncGeneric.cs
@@ -0,0 +1,189 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace AvalonDock.Commands
+{
+ ///
+ /// Class WeakFunc.
+ ///
+ ///
+ /// The type of the t result.
+ ///
+ ///
+ internal class WeakFunc : WeakFunc, IExecuteWithObjectAndResult
+ {
+ #region Private Fields
+
+ ///
+ /// The static function
+ ///
+ private Func _staticFunc;
+
+ #endregion Private Fields
+
+ #region Public Constructors
+
+ ///
+ /// Initializes a new instance of the WeakFunc class.
+ ///
+ /// The Func that will be associated to this instance.
+ public WeakFunc(Func func)
+ : this(func?.Target, func)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the WeakFunc class.
+ ///
+ /// The Func's owner.
+ /// The Func that will be associated to this instance.
+ [SuppressMessage(
+ "Microsoft.Design",
+ "CA1062:Validate arguments of public methods",
+ MessageId = "1",
+ Justification = "Method should fail with an exception if func is null.")]
+ public WeakFunc(object target, Func func)
+ {
+ if (func.Method.IsStatic)
+ {
+ _staticFunc = func;
+
+ if (target != null)
+ {
+ // Keep a reference to the target to control the
+ // WeakAction's lifetime.
+ Reference = new WeakReference(target);
+ }
+
+ return;
+ }
+ Method = func.Method;
+ FuncReference = new WeakReference(func.Target);
+ Reference = new WeakReference(target);
+ }
+
+ #endregion Public Constructors
+
+ #region Public Properties
+
+ ///
+ /// Gets a value indicating whether the Func's owner is still alive, or if it was collected
+ /// by the Garbage Collector already.
+ ///
+ /// true 如果 this instance is alive; 否则, false .
+ public override bool IsAlive
+ {
+ get
+ {
+ if (_staticFunc == null
+ && Reference == null)
+ {
+ return false;
+ }
+
+ if (_staticFunc != null)
+ {
+ if (Reference != null)
+ {
+ return Reference.IsAlive;
+ }
+
+ return true;
+ }
+
+ return Reference.IsAlive;
+ }
+ }
+
+ ///
+ /// Gets or sets the name of the method that this WeakFunc represents.
+ ///
+ /// The name of the method.
+ public override string MethodName
+ {
+ get
+ {
+ if (_staticFunc != null)
+ {
+ return _staticFunc.Method.Name;
+ }
+ return Method.Name;
+ }
+ }
+
+ #endregion Public Properties
+
+ #region Public Methods
+
+ ///
+ /// Executes the Func. This only happens if the Func's owner
+ /// is still alive. The Func's parameter is set to default(T).
+ ///
+ /// The result of the Func stored as reference.
+ public new TResult Execute()
+ {
+ return Execute(default);
+ }
+
+ ///
+ /// Executes the Func. This only happens if the Func's owner
+ /// is still alive.
+ ///
+ /// A parameter to be passed to the action.
+ /// The result of the Func stored as reference.
+ public TResult Execute(T parameter)
+ {
+ if (_staticFunc != null)
+ {
+ return _staticFunc(parameter);
+ }
+
+ var funcTarget = FuncTarget;
+
+ if (IsAlive)
+ {
+ if (Method != null
+ && FuncReference != null
+ && funcTarget != null)
+ {
+ return (TResult)Method.Invoke(
+ funcTarget,
+ new object[]
+ {
+ parameter
+ });
+ }
+ }
+
+ return default;
+ }
+
+ ///
+ /// Executes the Func with a parameter of type object. This parameter
+ /// will be casted to T. This method implements
+ /// and can be useful if you store multiple WeakFunc{T} instances but don't know in advance
+ /// what type T represents.
+ ///
+ /// The parameter that will be passed to the Func after
+ /// being casted to T.
+ /// The result of the execution as object, to be casted to T.
+ public object ExecuteWithObject(object parameter)
+ {
+ var parameterCasted = (T)parameter;
+ return Execute(parameterCasted);
+ }
+
+ ///
+ /// Sets all the funcs that this WeakFunc contains to null,
+ /// which is a signal for containing objects that this WeakFunc
+ /// should be deleted.
+ ///
+ public new void MarkForDeletion()
+ {
+ _staticFunc = null;
+ base.MarkForDeletion();
+ }
+
+ #endregion Public Methods
+ }
+}
\ No newline at end of file
diff --git a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs
index 5c6947b9..e8235e13 100644
--- a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs
+++ b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs
@@ -47,8 +47,8 @@ internal LayoutAnchorableFloatingWindowControl(LayoutAnchorableFloatingWindow mo
: base(model, isContentImmutable)
{
_model = model;
- HideWindowCommand = new RelayCommand((p) => OnExecuteHideWindowCommand(p), (p) => CanExecuteHideWindowCommand(p));
- CloseWindowCommand = new RelayCommand((p) => OnExecuteCloseWindowCommand(p), (p) => CanExecuteCloseWindowCommand(p));
+ HideWindowCommand = new RelayCommand((p) => OnExecuteHideWindowCommand(p), (p) => CanExecuteHideWindowCommand(p));
+ CloseWindowCommand = new RelayCommand((p) => OnExecuteCloseWindowCommand(p), (p) => CanExecuteCloseWindowCommand(p));
Activated += LayoutAnchorableFloatingWindowControl_Activated;
UpdateThemeResources();
MinWidth = _model.RootPanel.CalculatedDockMinWidth();
diff --git a/source/Components/AvalonDock/Controls/LayoutAnchorableItem.cs b/source/Components/AvalonDock/Controls/LayoutAnchorableItem.cs
index e281aba9..d1a1c8d3 100644
--- a/source/Components/AvalonDock/Controls/LayoutAnchorableItem.cs
+++ b/source/Components/AvalonDock/Controls/LayoutAnchorableItem.cs
@@ -242,9 +242,9 @@ protected override void Close()
///
protected override void InitDefaultCommands()
{
- _defaultHideCommand = new RelayCommand(ExecuteHideCommand, CanExecuteHideCommand);
- _defaultAutoHideCommand = new RelayCommand(ExecuteAutoHideCommand, CanExecuteAutoHideCommand);
- _defaultDockCommand = new RelayCommand(ExecuteDockCommand, CanExecuteDockCommand);
+ _defaultHideCommand = new RelayCommand(ExecuteHideCommand, CanExecuteHideCommand);
+ _defaultAutoHideCommand = new RelayCommand(ExecuteAutoHideCommand, CanExecuteAutoHideCommand);
+ _defaultDockCommand = new RelayCommand(ExecuteDockCommand, CanExecuteDockCommand);
base.InitDefaultCommands();
}
diff --git a/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs
index 40b488e6..faebff5f 100644
--- a/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs
+++ b/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs
@@ -47,8 +47,8 @@ internal LayoutDocumentFloatingWindowControl(LayoutDocumentFloatingWindow model,
: base(model, isContentImmutable)
{
_model = model;
- HideWindowCommand = new RelayCommand(OnExecuteHideWindowCommand, CanExecuteHideWindowCommand);
- CloseWindowCommand = new RelayCommand(OnExecuteCloseWindowCommand, CanExecuteCloseWindowCommand);
+ HideWindowCommand = new RelayCommand(OnExecuteHideWindowCommand, CanExecuteHideWindowCommand);
+ CloseWindowCommand = new RelayCommand(OnExecuteCloseWindowCommand, CanExecuteCloseWindowCommand);
Closed += (sender, args) => { Owner?.Focus(); };
UpdateThemeResources();
}
diff --git a/source/Components/AvalonDock/Controls/LayoutItem.cs b/source/Components/AvalonDock/Controls/LayoutItem.cs
index 608fea73..513c8e93 100644
--- a/source/Components/AvalonDock/Controls/LayoutItem.cs
+++ b/source/Components/AvalonDock/Controls/LayoutItem.cs
@@ -718,16 +718,16 @@ private void ExecuteMoveToPreviousTabGroupCommand(object parameter)
protected virtual void InitDefaultCommands()
{
- _defaultCloseCommand = new RelayCommand(ExecuteCloseCommand, CanExecuteCloseCommand);
- _defaultFloatCommand = new RelayCommand(ExecuteFloatCommand, CanExecuteFloatCommand);
- _defaultDockAsDocumentCommand = new RelayCommand(ExecuteDockAsDocumentCommand, CanExecuteDockAsDocumentCommand);
- _defaultCloseAllButThisCommand = new RelayCommand(ExecuteCloseAllButThisCommand, CanExecuteCloseAllButThisCommand);
- _defaultCloseAllCommand = new RelayCommand(ExecuteCloseAllCommand, CanExecuteCloseAllCommand);
- _defaultActivateCommand = new RelayCommand(ExecuteActivateCommand, CanExecuteActivateCommand);
- _defaultNewVerticalTabGroupCommand = new RelayCommand(ExecuteNewVerticalTabGroupCommand, CanExecuteNewVerticalTabGroupCommand);
- _defaultNewHorizontalTabGroupCommand = new RelayCommand(ExecuteNewHorizontalTabGroupCommand, CanExecuteNewHorizontalTabGroupCommand);
- _defaultMoveToNextTabGroupCommand = new RelayCommand(ExecuteMoveToNextTabGroupCommand, CanExecuteMoveToNextTabGroupCommand);
- _defaultMoveToPreviousTabGroupCommand = new RelayCommand(ExecuteMoveToPreviousTabGroupCommand, CanExecuteMoveToPreviousTabGroupCommand);
+ _defaultCloseCommand = new RelayCommand(ExecuteCloseCommand, CanExecuteCloseCommand);
+ _defaultFloatCommand = new RelayCommand(ExecuteFloatCommand, CanExecuteFloatCommand);
+ _defaultDockAsDocumentCommand = new RelayCommand(ExecuteDockAsDocumentCommand, CanExecuteDockAsDocumentCommand);
+ _defaultCloseAllButThisCommand = new RelayCommand(ExecuteCloseAllButThisCommand, CanExecuteCloseAllButThisCommand);
+ _defaultCloseAllCommand = new RelayCommand(ExecuteCloseAllCommand, CanExecuteCloseAllCommand);
+ _defaultActivateCommand = new RelayCommand(ExecuteActivateCommand, CanExecuteActivateCommand);
+ _defaultNewVerticalTabGroupCommand = new RelayCommand(ExecuteNewVerticalTabGroupCommand, CanExecuteNewVerticalTabGroupCommand);
+ _defaultNewHorizontalTabGroupCommand = new RelayCommand(ExecuteNewHorizontalTabGroupCommand, CanExecuteNewHorizontalTabGroupCommand);
+ _defaultMoveToNextTabGroupCommand = new RelayCommand(ExecuteMoveToNextTabGroupCommand, CanExecuteMoveToNextTabGroupCommand);
+ _defaultMoveToPreviousTabGroupCommand = new RelayCommand(ExecuteMoveToPreviousTabGroupCommand, CanExecuteMoveToPreviousTabGroupCommand);
}
protected virtual void ClearDefaultBindings()