Last active
November 4, 2020 13:40
-
-
Save Y-Koji/2fd810b2d3ea44294f015307c2faf867 to your computer and use it in GitHub Desktop.
WPF Support Codes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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