using System; using System.ComponentModel; using System.Windows; using System.Windows.Input; using System.Windows.Markup; using System.Windows.Media; using Hardcodet.Wpf.TaskbarNotification; namespace FSI.BT.Tools.Commands { /// /// Basic implementation of the /// interface, which is also accessible as a markup /// extension. /// public abstract class CommandBase : MarkupExtension, ICommand where T : class, ICommand, new() { /// /// A singleton instance. /// private static T? command; /// /// Gets a shared command instance. /// public override object ProvideValue(IServiceProvider serviceProvider) { if (command == null) command = new T(); return command; } /// /// Fires when changes occur that affect whether /// or not the command should execute. /// public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } /// /// 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 null. /// public abstract void Execute(object parameter); /// /// Defines the method that determines whether the command /// can execute in its current state. /// /// /// This default implementation always returns true. /// /// Data used by the command. /// If the command does not require data to be passed, /// this object can be set to null. /// public virtual bool CanExecute(object parameter) { return !IsDesignMode; } public static bool IsDesignMode { get { return (bool) DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(FrameworkElement)) .Metadata.DefaultValue; } } /// /// Resolves the window that owns the TaskbarIcon class. /// /// /// Window protected Window? GetTaskbarWindow(object commandParameter) { if (IsDesignMode) return null; // get the showcase window off the taskbar icon var tb = commandParameter as TaskbarIcon; return tb == null ? null : TryFindParent(tb); } #region TryFindParent helper /// /// Finds a parent of a given item on the visual tree. /// /// The type of the queried item. /// A direct or indirect child of the /// queried item. /// The first parent item that matches the submitted /// type parameter. If not matching item can be found, a null /// reference is being returned. public static TParent? TryFindParent(DependencyObject child) where TParent : DependencyObject { //get parent item DependencyObject parentObject = GetParentObject(child); //we've reached the end of the tree if (parentObject == null) return null; //check if the parent matches the type we're looking for if (parentObject is TParent parent) { return parent; } //use recursion to proceed with next level return TryFindParent(parentObject); } /// /// This method is an alternative to WPF's /// method, which also /// supports content elements. Keep in mind that for content element, /// this method falls back to the logical tree of the element! /// /// The item to be processed. /// The submitted item's parent, if available. Otherwise /// null. public static DependencyObject? GetParentObject(DependencyObject child) { if (child == null) return null; if (child is ContentElement contentElement) { DependencyObject parent = ContentOperations.GetParent(contentElement); if (parent != null) return parent; FrameworkContentElement? fce = contentElement as FrameworkContentElement; return fce?.Parent; } //if it's not a ContentElement, rely on VisualTreeHelper return VisualTreeHelper.GetParent(child); } #endregion } }