mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-03-18 07:26:36 +08:00
整理整理
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace AIStudio.Wpf.DiagramDesigner.Additionals.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="ICommand"/> whose delegates can be attached for <see cref="Execute"/> and <see cref="CanExecute"/>.
|
||||
/// </summary>
|
||||
public abstract class DelegateCommandBase : ICommand, IActiveAware
|
||||
{
|
||||
private bool _isActive;
|
||||
|
||||
private SynchronizationContext _synchronizationContext;
|
||||
private readonly HashSet<string> _observedPropertiesExpressions = new HashSet<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of a <see cref="DelegateCommandBase"/>, specifying both the execute action and the can execute function.
|
||||
/// </summary>
|
||||
protected DelegateCommandBase()
|
||||
{
|
||||
_synchronizationContext = SynchronizationContext.Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when changes occur that affect whether or not the command should execute.
|
||||
/// </summary>
|
||||
public virtual event EventHandler CanExecuteChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Raises <see cref="ICommand.CanExecuteChanged"/> so every
|
||||
/// command invoker can requery <see cref="ICommand.CanExecute"/>.
|
||||
/// </summary>
|
||||
protected virtual void OnCanExecuteChanged()
|
||||
{
|
||||
var handler = CanExecuteChanged;
|
||||
if (handler != null)
|
||||
{
|
||||
if (_synchronizationContext != null && _synchronizationContext != SynchronizationContext.Current)
|
||||
_synchronizationContext.Post((o) => handler.Invoke(this, EventArgs.Empty), null);
|
||||
else
|
||||
handler.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises <see cref="CanExecuteChanged"/> so every command invoker
|
||||
/// can requery to check if the command can execute.
|
||||
/// </summary>
|
||||
/// <remarks>Note that this will trigger the execution of <see cref="CanExecuteChanged"/> once for each invoker.</remarks>
|
||||
[SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate")]
|
||||
public void RaiseCanExecuteChanged()
|
||||
{
|
||||
OnCanExecuteChanged();
|
||||
}
|
||||
|
||||
void ICommand.Execute(object parameter)
|
||||
{
|
||||
Execute(parameter);
|
||||
}
|
||||
|
||||
bool ICommand.CanExecute(object parameter)
|
||||
{
|
||||
return CanExecute(parameter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the internal invocation of <see cref="ICommand.Execute(object)"/>
|
||||
/// </summary>
|
||||
/// <param name="parameter">Command Parameter</param>
|
||||
protected abstract void Execute(object parameter);
|
||||
|
||||
/// <summary>
|
||||
/// Handle the internal invocation of <see cref="ICommand.CanExecute(object)"/>
|
||||
/// </summary>
|
||||
/// <param name="parameter"></param>
|
||||
/// <returns><see langword="true"/> if the Command Can Execute, otherwise <see langword="false" /></returns>
|
||||
protected abstract bool CanExecute(object parameter);
|
||||
|
||||
/// <summary>
|
||||
/// Observes a property that implements INotifyPropertyChanged, and automatically calls DelegateCommandBase.RaiseCanExecuteChanged on property changed notifications.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The object type containing the property specified in the expression.</typeparam>
|
||||
/// <param name="propertyExpression">The property expression. Example: ObservesProperty(() => PropertyName).</param>
|
||||
protected internal void ObservesPropertyInternal<T>(Expression<Func<T>> propertyExpression)
|
||||
{
|
||||
if (_observedPropertiesExpressions.Contains(propertyExpression.ToString()))
|
||||
{
|
||||
throw new ArgumentException($"{propertyExpression.ToString()} is already being observed.",
|
||||
nameof(propertyExpression));
|
||||
}
|
||||
else
|
||||
{
|
||||
_observedPropertiesExpressions.Add(propertyExpression.ToString());
|
||||
PropertyObserver.Observes(propertyExpression, RaiseCanExecuteChanged);
|
||||
}
|
||||
}
|
||||
|
||||
#region IsActive
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the object is active.
|
||||
/// </summary>
|
||||
/// <value><see langword="true" /> if the object is active; otherwise <see langword="false" />.</value>
|
||||
public bool IsActive
|
||||
{
|
||||
get { return _isActive; }
|
||||
set
|
||||
{
|
||||
if (_isActive != value)
|
||||
{
|
||||
_isActive = value;
|
||||
OnIsActiveChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fired if the <see cref="IsActive"/> property changes.
|
||||
/// </summary>
|
||||
public virtual event EventHandler IsActiveChanged;
|
||||
|
||||
/// <summary>
|
||||
/// This raises the <see cref="DelegateCommandBase.IsActiveChanged"/> event.
|
||||
/// </summary>
|
||||
protected virtual void OnIsActiveChanged()
|
||||
{
|
||||
IsActiveChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user