You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
5.6 KiB
203 lines
5.6 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Windows; |
|
using System.Windows.Input; |
|
using System.Windows.Controls; |
|
using System.Reflection; |
|
using System.Windows.Media; |
|
|
|
namespace SharpDevelop.XamlDesigner.Commanding |
|
{ |
|
public static class CommandHelper |
|
{ |
|
static CommandHelper() |
|
{ |
|
CommandManager.RequerySuggested += RequerySuggestedDelegate; |
|
} |
|
|
|
static EventHandler RequerySuggestedDelegate = RequerySuggested; |
|
static DefaultContainerStyles DefaultContainerStyles = new DefaultContainerStyles(); |
|
static List<WeakReference> TrackingElements = new List<WeakReference>(); |
|
|
|
static MethodInfo CommandConverter_GetKnownCommand = typeof(CommandConverter) |
|
.GetMethod("GetKnownCommand", BindingFlags.NonPublic | BindingFlags.Static); |
|
|
|
public static string GetCommand(DependencyObject obj) |
|
{ |
|
return (string)obj.GetValue(CommandProperty); |
|
} |
|
|
|
public static void SetCommand(DependencyObject obj, object value) |
|
{ |
|
obj.SetValue(CommandProperty, value); |
|
} |
|
|
|
public static readonly DependencyProperty CommandProperty = |
|
DependencyProperty.RegisterAttached("Command", typeof(string), typeof(CommandHelper), |
|
new FrameworkPropertyMetadata(CommandPropertyChanged)); |
|
|
|
//public static object GetCommandTarget(DependencyObject obj) |
|
//{ |
|
// return (object)obj.GetValue(CommandTargetProperty); |
|
//} |
|
|
|
//public static void SetCommandTarget(DependencyObject obj, object value) |
|
//{ |
|
// obj.SetValue(CommandTargetProperty, value); |
|
//} |
|
|
|
//public static readonly DependencyProperty CommandTargetProperty = |
|
// DependencyProperty.RegisterAttached("CommandTarget", typeof(object), typeof(CommandHelper), |
|
// new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); |
|
|
|
public static CommandView GetCommandView(DependencyObject obj) |
|
{ |
|
return (CommandView)obj.GetValue(CommandViewProperty); |
|
} |
|
|
|
public static void SetCommandView(DependencyObject obj, CommandView value) |
|
{ |
|
obj.SetValue(CommandViewProperty, value); |
|
} |
|
|
|
public static readonly DependencyProperty CommandViewProperty = |
|
DependencyProperty.RegisterAttached("CommandView", typeof(CommandView), typeof(CommandHelper)); |
|
|
|
static void CommandPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) |
|
{ |
|
var commandName = (string)e.NewValue; |
|
var element = target as FrameworkElement; |
|
var view = element.TryFindResource(commandName) as CommandView; |
|
|
|
if (view == null) { |
|
view = new CommandView(); |
|
view.Text = commandName; |
|
} |
|
|
|
view.CommandName = commandName; |
|
|
|
SetCommandView(element, view); |
|
|
|
TrackingElements.Add(new WeakReference(element)); |
|
|
|
var routedCommand = CommandConverter_GetKnownCommand.Invoke(null, new[] { commandName, null }) as RoutedCommand; |
|
if (routedCommand != null) { |
|
view.InitializeFromRoutedCommand(routedCommand); |
|
} |
|
|
|
var key = new ContainerStyleKey(element.GetType()); |
|
var style = element.TryFindResource(key) as Style; |
|
if (style == null) { |
|
style = DefaultContainerStyles[key] as Style; |
|
} |
|
|
|
style.BasedOn = element.FindResource(element.GetType()) as Style; |
|
element.Style = style; |
|
|
|
if (view.Shortcut != null) { |
|
Application.Current.MainWindow.InputBindings.Add( |
|
new InputBinding(new ShortcutCommand() { Sender = element }, view.Shortcut)); |
|
} |
|
} |
|
|
|
public static void RequerySuggested(object sender, EventArgs e) |
|
{ |
|
foreach (var weak in TrackingElements) { |
|
if (weak.IsAlive) { |
|
var element = weak.Target as FrameworkElement; |
|
if (element.IsLoaded) { |
|
var handler = FindCommandHandler(element); |
|
var view = GetCommandView(element); |
|
if (handler != null) { |
|
view.IsEnabled = handler.CanExecute(null); |
|
} |
|
else { |
|
view.IsEnabled = false; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
public static void TryExecuteCommand(object sender) |
|
{ |
|
var handler = FindCommandHandler(sender); |
|
if (handler != null) { |
|
handler.Execute(null); |
|
} |
|
} |
|
|
|
public static CommandBase FindCommandHandler(object sender) |
|
{ |
|
CommandBase handler = null; |
|
var d = sender as DependencyObject; |
|
if (d != null) { |
|
var commandView = GetCommandView(d); |
|
if (commandView != null) { |
|
//var target = GetCommandTarget(d); |
|
//if (target != null) { |
|
// handler = FindCommandHandler(target, commandView.CommandName); |
|
//} |
|
if (handler == null) { |
|
handler = FindCommandHandler(sender, commandView.CommandName); |
|
} |
|
} |
|
} |
|
return handler; |
|
} |
|
|
|
static CommandBase FindCommandHandler(object start, string commandName) |
|
{ |
|
foreach (var step in GetCommandChain(start)) { |
|
var hasCommands = step as IHasCommands; |
|
if (hasCommands != null) { |
|
foreach (var commandHandler in hasCommands.Commands) { |
|
if (commandHandler.CommandName == commandName) { |
|
return commandHandler; |
|
} |
|
} |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
static IEnumerable<object> GetCommandChain(object start) |
|
{ |
|
yield return start; |
|
var d = start as DependencyObject; |
|
if (d != null) { |
|
if (d != start) { |
|
yield return d; |
|
} |
|
var element = d as FrameworkElement; |
|
if (element != null) { |
|
yield return element.DataContext; |
|
} |
|
d = VisualTreeHelper.GetParent(d); |
|
} |
|
} |
|
|
|
class ShortcutCommand : ICommand |
|
{ |
|
public FrameworkElement Sender; |
|
|
|
public bool CanExecute(object parameter) |
|
{ |
|
var handler = FindCommandHandler(Sender); |
|
if (handler != null) { |
|
return handler.CanExecute(parameter); |
|
} |
|
return false; |
|
} |
|
|
|
public event EventHandler CanExecuteChanged; |
|
|
|
public void Execute(object parameter) |
|
{ |
|
CommandHelper.TryExecuteCommand(Sender); |
|
} |
|
} |
|
} |
|
}
|
|
|