Skip to content

Instantly share code, notes, and snippets.

@Y-Koji
Last active November 4, 2020 13:40
Show Gist options
  • Save Y-Koji/2fd810b2d3ea44294f015307c2faf867 to your computer and use it in GitHub Desktop.
Save Y-Koji/2fd810b2d3ea44294f015307c2faf867 to your computer and use it in GitHub Desktop.
WPF Support Codes
using System;
using System.Windows.Input;
public class ActionCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private ActionCommand() { }
private Func<object, bool> _CanExecute { get; set; }
private Action<object> _Execute { get; set; }
public bool CanExecute(object parameter)
=> _CanExecute?.Invoke(parameter) ?? true;
public void Execute(object parameter)
=> _Execute?.Invoke(parameter);
public static ICommand Create(Func<object, bool> canExecute, Action<object> execute)
{
ActionCommand actionCommand = new ActionCommand();
actionCommand._CanExecute = canExecute;
actionCommand._Execute = execute;
return actionCommand;
}
public static ICommand Create(Action<object> execute)
=> Create(obj => true, execute);
public static ICommand Create(Action execute)
=> Create(obj => true, obj => execute?.Invoke());
}
using System;
using System.Reflection;
using System.Windows;
using System.Windows.Input;
using System.Windows.Markup;
[MarkupExtensionReturnType(typeof(EventHandler))]
public class EventCommandExtension : MarkupExtension
{
private static MethodInfo GenericEventHandlerType { get; } =
typeof(EventCommandExtension).GetMethod(nameof(GenericEventHandler), BindingFlags.NonPublic | BindingFlags.Instance);
private ICommand Command { get; set; } = default;
private string Path { get; } = string.Empty;
private object DataContext { get; set; } = default;
public EventCommandExtension(string path)
{
Path = path;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
var pvt = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (default != pvt)
{
if (pvt.TargetObject is FrameworkElement element)
{
DataContext = element.DataContext;
}
Type type =
pvt.TargetProperty is EventInfo ei ? ei.EventHandlerType :
pvt.TargetProperty is MethodInfo mi ? mi.GetParameters()[1].ParameterType :
default;
if (default != type)
{
var argType = type.GetMethod(nameof(MethodInfo.Invoke)).GetParameters()[1].ParameterType;
var genericMethod = GenericEventHandlerType.MakeGenericMethod(argType);
return Delegate.CreateDelegate(type, this, genericMethod);
}
}
return default;
}
private void GenericEventHandler<T>(object sender, T e)
{
Command = ParsePropertyPath(DataContext, Path) as ICommand;
// コマンドを呼び出す
if (Command?.CanExecute(e) ?? false)
{
Command.Execute(e);
}
}
/// <summary>
/// target引数で渡されたオブジェクトに対し、pathで示されたプロパティをリフレクションを用いて取得します。
/// </summary>
/// <param name="target"></param>
/// <param name="path"></param>
/// <returns></returns>
private static object ParsePropertyPath(object target, string path)
{
// DataContextがdefaultの場合の対処
if (default == target)
return default;
var props = path.Split('.');
foreach (var prop in props)
{
target = target?.GetType()?.GetProperty(prop)?.GetValue(target);
if (default == target)
{
break;
}
}
return target;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment