Skip to content

Instantly share code, notes, and snippets.

@X39
Created March 22, 2018 19:38
Show Gist options
  • Save X39/67ea59ba88c3d8c6d11e41e6248696d9 to your computer and use it in GitHub Desktop.
Save X39/67ea59ba88c3d8c6d11e41e6248696d9 to your computer and use it in GitHub Desktop.
T4 Template for AttachedProperties to wpf control events (UIControl, FrameworkElement and Control)
<#@ 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