Created
March 22, 2018 19:38
-
-
Save X39/67ea59ba88c3d8c6d11e41e6248696d9 to your computer and use it in GitHub Desktop.
T4 Template for AttachedProperties to wpf control events (UIControl, FrameworkElement and Control)
This file contains 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
<#@ template debug="true" hostspecific="false" language="C#" #> | |
<#@ assembly name="System.Core" #> | |
<#@ assembly name="PresentationCore" #> | |
<#@ assembly name="PresentationFramework" #> | |
<#@ import namespace="System.Linq" #> | |
<#@ import namespace="System.Text" #> | |
<#@ import namespace="System.Windows" #> | |
<#@ import namespace="System.Windows.Controls" #> | |
<#@ import namespace="System.Collections.Generic" #> | |
<#@ output extension=".cs" #> | |
using System; | |
using System.Reflection; | |
using System.Windows; | |
using System.Windows.Controls; | |
using System.Windows.Input; | |
namespace AttachedProperties | |
{ | |
<# | |
bool comma = false; | |
var AllEvents = new Type[] { typeof(Control) }.SelectMany((t) => t.GetEvents()).Distinct().ToArray(); | |
foreach (var ev in AllEvents) | |
{ | |
#> | |
public interface IOn<#= ev.Name #> { void On<#= ev.Name #>(<#= ev.DeclaringType.Name #> sender, <#= GetFullTypeName(ev.EventHandlerType.GetMethod("Invoke").GetParameters().Last().ParameterType) #> e); } | |
<# | |
} | |
#> | |
public static class AttachedDataContext | |
{ | |
public static DependencyProperty DataContextProperty = | |
DependencyProperty.RegisterAttached("DataContext", | |
typeof(object), | |
typeof(AttachedDataContext), | |
new UIPropertyMetadata(DataContextChanged)); | |
public static object GetDataContext(UIElement target) => (object)target.GetValue(DataContextProperty); | |
public static void SetDataContext(UIElement target, object value) => target.SetValue(DataContextProperty, value); | |
static void DataContextChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) | |
{ | |
var type = target.GetType(); | |
if ((e.NewValue != null) && (e.OldValue == null)) | |
{ | |
OnAdd(type, target, e); | |
} | |
else if ((e.NewValue == null) && (e.OldValue != null)) | |
{ | |
OnRemove(type, target, e); | |
} | |
} | |
static void OnAdd(Type type, DependencyObject target, DependencyPropertyChangedEventArgs e) | |
{ | |
<# | |
foreach (var ev in AllEvents) | |
{ | |
#> | |
if (e.NewValue is IOn<#= ev.Name #>) | |
{ | |
var evinfo = type.GetEvent("<#= ev.Name #>"); | |
var mtinfo = typeof(AttachedDataContext).GetMethod("On<#= ev.Name #>"); | |
evinfo.AddEventHandler(target, Delegate.CreateDelegate(evinfo.EventHandlerType, mtinfo)); | |
} | |
<# | |
} | |
#> | |
} | |
static void OnRemove(Type type, DependencyObject target, DependencyPropertyChangedEventArgs e) | |
{ | |
<# | |
foreach (var ev in AllEvents) | |
{ | |
#> | |
if (e.NewValue is IOn<#= ev.Name #>) | |
{ | |
var evinfo = type.GetEvent("<#= ev.Name #>"); | |
var mtinfo = typeof(AttachedDataContext).GetMethod("On<#= ev.Name #>"); | |
evinfo.RemoveEventHandler(target, Delegate.CreateDelegate(evinfo.EventHandlerType, mtinfo)); | |
} | |
<# | |
} | |
#> | |
} | |
<# | |
comma = false; | |
foreach (var ev in AllEvents) | |
{ | |
#> | |
public static void On<#= ev.Name #>(object sender, <#= GetFullTypeName(ev.EventHandlerType.GetMethod("Invoke").GetParameters().Last().ParameterType) #> e) | |
{ | |
if (sender is <#= ev.DeclaringType.Name #> cntrl) | |
{ | |
var dc = GetDataContext(cntrl) as IOn<#= ev.Name #>; | |
dc.On<#= ev.Name #>(cntrl, e); | |
} | |
} | |
<# | |
} | |
#> | |
} | |
<# | |
var attEvs = from ev in AllEvents where !ev.Name.StartsWith("Preview") select ev; | |
foreach(var ev in attEvs) | |
{ | |
#> | |
public class <#= ev.Name #> | |
{ | |
public static DependencyProperty CommandProperty = | |
DependencyProperty.RegisterAttached("Command", | |
typeof(ICommand), | |
typeof(<#= ev.Name #>), | |
new UIPropertyMetadata(CommandChanged)); | |
public static DependencyProperty CommandParameterProperty = | |
DependencyProperty.RegisterAttached("CommandParameter", | |
typeof(object), | |
typeof(<#= ev.Name #>), | |
new UIPropertyMetadata(null)); | |
public static ICommand GetCommand(<#= ev.DeclaringType.Name #> target) => (ICommand)target.GetValue(CommandProperty); | |
public static void SetCommand(<#= ev.DeclaringType.Name #> target, ICommand value) => target.SetValue(CommandProperty, value); | |
public static object GetCommandParameter(<#= ev.DeclaringType.Name #> target) => target.GetValue(CommandParameterProperty); | |
public static void SetCommandParameter(<#= ev.DeclaringType.Name #> target, object value) => target.SetValue(CommandParameterProperty, value); | |
private static void CommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) | |
{ | |
var type = target.GetType(); | |
var ev = type.GetEvent("<#= ev.Name #>"); | |
var method = typeof(<#= ev.Name #>).GetMethod("On<#= ev.Name #>"); | |
if ((e.NewValue != null) && (e.OldValue == null)) | |
{ | |
ev.AddEventHandler(target, Delegate.CreateDelegate(ev.EventHandlerType, method)); | |
} | |
else if ((e.NewValue == null) && (e.OldValue != null)) | |
{ | |
ev.RemoveEventHandler(target, Delegate.CreateDelegate(ev.EventHandlerType, method)); | |
} | |
} | |
public static void On<#= ev.Name #>(object sender, EventArgs e) | |
{ | |
var control = sender as <#= ev.DeclaringType.Name #>; | |
var command = (ICommand)control.GetValue(CommandProperty); | |
var commandParameter = control.GetValue(CommandParameterProperty); | |
command.Execute(commandParameter); | |
} | |
} | |
<# | |
} | |
#> | |
} | |
<#+ | |
private string GetFullTypeName(Type t) | |
{ | |
var builder = new StringBuilder(); | |
builder.Append(t.Namespace); | |
builder.Append('.'); | |
if (t.IsGenericType) | |
{ | |
builder.Append(t.Name.Substring(0, t.Name.IndexOf('`'))); | |
builder.Append('<'); | |
bool comma = false; | |
foreach(var generic in t.GenericTypeArguments) | |
{ | |
builder.Append(GetFullTypeName(generic)); | |
if (comma) | |
{ | |
builder.Append(", "); | |
} | |
else | |
{ | |
comma = true; | |
} | |
} | |
builder.Append('>'); | |
} | |
else | |
{ | |
builder.Append(t.Name); | |
} | |
return builder.ToString(); | |
} | |
#> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment