登録の簡素化とDependencyPropertyの使用

WPF / Silverlightを使用する場合、主にコントロールを作成するときに、定期的にカスタムDependencyPropertyを作成する必要があります。 広告や広告の標準的なアプローチは理想的ではなく、欠点もあります。これについては以下で説明します。 それに応じて、登録の記録を簡素化し、DependencyPropertyを使用するというアイデアが生まれました。



はじめに、標準のDependencyProperty宣言コードを次に示します。

public class SomeDependecyObject : DependencyObject { public static readonly DependencyProperty IntValueProperty = DependencyProperty.Register("IntValue", typeof(int), typeof(SomeDependecyObject), new UIPropertyMetadata(1, OnIntValuePropertyChanged)); public int IntValue { get { return (int)GetValue(IntValueProperty); } set { SetValue(IntValueProperty, value); } } private static void OnIntValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { int newPropertyValue = (int)e.NewValue; SomeDependecyObject instance = (SomeDependecyObject)d; // Perform callback action. } }
      
      





このアプローチの欠点:



拡張オプションコード:

 public class SomeDependecyObject : DependencyObject { public static readonly DependencyProperty IntValueProperty = DependencyProperty<SomeDependecyObject>.Register(x => x.IntValue, 1, x => x.OnIntValuePropertyChanged); public int IntValue { get { return (int)GetValue(IntValueProperty); } set { SetValue(IntValueProperty, value); } } private void OnIntValuePropertyChanged(DependencyPropertyChangedEventArgs<int> e) { } }
      
      





この実施形態では、Registerメソッドは、静的コールバックではなく、式としてのプロパティ、特定のタイプのデフォルト値を受け入れます。 コールバックメソッドは、古いプロパティ値と新しいプロパティ値がプロパティタイプにキャストされるDependencyPropertyChangedEventArgsクラスのジェネリックのインスタンスを受け入れます。 録音自体も簡素化されました。 次に、このようなレコードを適用できるクラスのコードを提供します。



DependecyPropertyクラスのカスタムジェネリックコード:

 public static class DependencyProperty<T> where T : DependencyObject { public static DependencyProperty Register<TProperty>(Expression<Func<T, TProperty>> propertyExpression) { return Register<TProperty>(propertyExpression, default(TProperty), null); } public static DependencyProperty Register<TProperty>(Expression<Func<T, TProperty>> propertyExpression, TProperty defaultValue) { return Register<TProperty>(propertyExpression, defaultValue, null); } public static DependencyProperty Register<TProperty>(Expression<Func<T, TProperty>> propertyExpression, Func<T, PropertyChangedCallback<TProperty>> propertyChangedCallbackFunc) { return Register<TProperty>(propertyExpression, default(TProperty), propertyChangedCallbackFunc); } public static DependencyProperty Register<TProperty>(Expression<Func<T, TProperty>> propertyExpression, TProperty defaultValue, Func<T, PropertyChangedCallback<TProperty>> propertyChangedCallbackFunc) { string propertyName = propertyExpression.RetrieveMemberName(); PropertyChangedCallback callback = ConvertCallback(propertyChangedCallbackFunc); return DependencyProperty.Register(propertyName, typeof(TProperty), typeof(T), new PropertyMetadata(defaultValue, callback)); } private static PropertyChangedCallback ConvertCallback<TProperty>(Func<T, PropertyChangedCallback<TProperty>> propertyChangedCallbackFunc) { if (propertyChangedCallbackFunc == null) return null; return new PropertyChangedCallback((d, e) => { PropertyChangedCallback<TProperty> callback = propertyChangedCallbackFunc((T)d); if (callback != null) callback(new DependencyPropertyChangedEventArgs<TProperty>(e)); }); } } public delegate void PropertyChangedCallback<TProperty>(DependencyPropertyChangedEventArgs<TProperty> e);
      
      





このクラスは、ジェネリックパラメーターとして、DependencyObject型を受け入れ、オーバーロードされた複数のRegisterメソッドを含みます。 Registerメソッドは、プロパティ式から名前を取得し、コールバックを変換し、標準メソッドを使用してDependencyPropertyを作成します。



DependecyPropertyChangedEventArgsクラスコード:

 public class DependencyPropertyChangedEventArgs<T> : EventArgs { public DependencyPropertyChangedEventArgs(DependencyPropertyChangedEventArgs e) { NewValue = (T)e.NewValue; OldValue = (T)e.OldValue; Property = e.Property; } public T NewValue { get; private set; } public T OldValue { get; private set; } public DependencyProperty Property { get; private set; } }
      
      





式によってプロパティ名を取得するために使用される、オプションのExpressionExtensionsクラスのコード:

 public static class ExpressionExtensions { public static string RetrieveMemberName<TArg, TRes>(this Expression<Func<TArg, TRes>> propertyExpression) { MemberExpression memberExpression = propertyExpression.Body as MemberExpression; if (memberExpression == null) { UnaryExpression unaryExpression = propertyExpression.Body as UnaryExpression; if (unaryExpression != null) memberExpression = unaryExpression.Operand as MemberExpression; } if (memberExpression != null) { ParameterExpression parameterExpression = memberExpression.Expression as ParameterExpression; if (parameterExpression != null && parameterExpression.Name == propertyExpression.Parameters[0].Name) return memberExpression.Member.Name; } throw new ArgumentException("Invalid expression.", "propertyExpression"); } }
      
      






All Articles