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
}
}