定义WPF属性太长:
public static readonly DependencyProperty FooProperty =
DependencyProperty.Register("Foo", typeof(string), typeof(FooClass), new PropertyMetadata("Foooooo"));
我有一个辅助方法,使它缩短一点:
public static readonly DependencyProperty FooProperty =
WpfUtils.Property<string, FooControl>("Foo", "Foooooo");
代码:
public partial class WpfUtils
{
public static DependencyProperty Property<T, TClass>(string name)
{
return Property<T, TClass>(name, default(T));
}
public static DependencyProperty Property<T, TClass>(string name, T defaultValue)
{
return DependencyProperty.Register(name, typeof(T), typeof(TClass), new PropertyMetadata(defaultValue));
}
}
周围有更好的助手吗?
答案 0 :(得分:6)
这是一些代码。这段代码是邪恶的,但我想展示如何在不使用Cecil的情况下执行此操作,或者必须创建sourceforge项目: - )
要使用它,请致电:
public static readonly DependencyProperty FooProperty = D.P();
代码是:
public class D
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static DependencyProperty P()
{
StackTrace stackTrace = new StackTrace();
StackFrame oneUp = stackTrace.GetFrame(1);
MethodBase callingMethod = oneUp.GetMethod();
if (!(callingMethod is ConstructorInfo))
{
throw new InvalidOperationException("This method must be called from a static constructor/initializer");
}
byte[] staticConstructorCode = callingMethod.GetMethodBody().GetILAsByteArray();
int offsetAfterThisCall = oneUp.GetILOffset() + 5;
while (staticConstructorCode[offsetAfterThisCall] == OpCodes.Nop.Value)
{
offsetAfterThisCall++;
}
if (staticConstructorCode[offsetAfterThisCall] != OpCodes.Stsfld.Value)
{
throw new InvalidOperationException("Unexpected IL");
}
int token = BitConverter.ToInt32(staticConstructorCode, offsetAfterThisCall + 1);
FieldInfo field = callingMethod.Module.ResolveField(token);
if (!field.Name.EndsWith("Property") || field.FieldType != typeof(DependencyProperty))
{
throw new NotSupportedException("The field the return value of this method will be stored in must be named xxxProperty and be of type DependencyProperty");
}
string name = field.Name.Substring(0, field.Name.Length - "Property".Length);
return DependencyProperty.Register(name, callingMethod.DeclaringType.GetProperty(name).PropertyType, callingMethod.DeclaringType);
}
}
答案 1 :(得分:5)
这是我的尝试。它比Alun Harford的IL读数方法更安全。
此助手具有以下功能:
首先,我将展示用法:
public class Tester : DependencyObject
{
public int Foo
{
get { return (int)GetValue(FooProperty); }
set { SetValue(FooProperty, value); }
}
public static readonly DependencyProperty FooProperty =
For<Tester>.Register(o => o.Foo, 0, onFooChanged);
private static void onFooChanged(Tester obj, DependencyPropertyChangedEventArgs<int> e)
{
}
public string Attached
{
get { return (string)GetValue(AttachedProperty); }
set { SetValue(AttachedProperty, value); }
}
public static readonly DependencyProperty AttachedProperty =
For<Tester>.RegisterAttached(o => o.Attached, "default", onAttachedChanged);
private static void onAttachedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs<string> e)
{
}
}
以下是实施:
public static class For<TOwner>
where TOwner : DependencyObject
{
public static DependencyProperty Register<TProperty>(
Expression<Func<TOwner,TProperty>> property,
TProperty defaultValue,
Action<TOwner, DependencyPropertyChangedEventArgs<TProperty>> callback)
{
return DependencyProperty.Register(
getName(property),
typeof(TProperty),
typeof(TOwner),
new FrameworkPropertyMetadata(
defaultValue,
(o, args) => callback((TOwner)o, new DependencyPropertyChangedEventArgs<TProperty>(args))));
}
public static DependencyProperty RegisterAttached<TProperty>(
Expression<Func<TOwner,TProperty>> property,
TProperty defaultValue,
Action<DependencyObject, DependencyPropertyChangedEventArgs<TProperty>> callback)
{
return DependencyProperty.RegisterAttached(
getName(property),
typeof(TProperty),
typeof(TOwner),
new FrameworkPropertyMetadata(
defaultValue,
(o, args) => callback(o, new DependencyPropertyChangedEventArgs<TProperty>(args))));
}
private static string getName<T>(Expression<Func<TOwner,T>> property)
{
var name = ((MemberExpression)property.Body).Member.Name;
return name;
}
}
public struct DependencyPropertyChangedEventArgs<T>
{
public DependencyPropertyChangedEventArgs(DependencyPropertyChangedEventArgs source)
{
m_property = source.Property;
m_oldValue = (T)source.OldValue;
m_newValue = (T)source.NewValue;
}
private readonly DependencyProperty m_property;
public DependencyProperty Property { get { return m_property; } }
private readonly T m_oldValue;
public T OldValue { get { return m_oldValue; } }
private readonly T m_newValue;
public T NewValue { get { return m_newValue; } }
}
答案 2 :(得分:4)
我同意依赖属性很长很痛苦。我不使用帮助程序,但Visual Studio有一个很好的内置代码片段,您可以通过键入wpfdp来使用它。
这就是我如何快速填写一堆依赖属性。
答案 3 :(得分:0)
对于那些使用resharper的人,我使用以下模板
//DependencyProperty $PropertyName$
public static readonly DependencyProperty $PropertyName$Property =
DependencyProperty.Register("$PropertyName$", typeof($PropertyType$), typeof($SelfType$),
new FrameworkPropertyMetadata($DefaultValue$, $PropertyName$ChangedCallback, $PropertyName$CoerceValue));
public $PropertyType$ $PropertyName${
set { SetValue($PropertyName$Property, value); }
get { return ($PropertyType$)GetValue($PropertyName$Property); }
}
private static void $PropertyName$ChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e){
$SelfType$ owner = d as $SelfType$;
if(owner!=null){}
}
private static object $PropertyName$CoerceValue(DependencyObject d, object value) {
$PropertyType$ val = ($PropertyType$)value;
return value;
}
我只在可以申报会员的地方展示 我还设置$ SelfType $扩展为父类型,这里是类名