PropertyChanged
ゲッターで複数のイベントを発生させる標準的な方法よりもクリーンな方法でプロパティ間の依存関係を定義できるようにする、WPF ビューモデル基本クラスへの小さな拡張機能を作成しています。
したがって、代わりに:
public int ThisProperty
{
get
{
thisProperty = value;
RaisePropertyChangedEvent("ThisProperty");
RaisePropertyChangedEvent("FirstDependentProperty");
RaisePropertyChangedEvent("SecondDependentProperty");
}
}
ViewModels コンストラクターで次のようなことができるようにしたいと考えています。
RegisterDependencies("This Property",
"FirstDependentProperty", "SecondDependentProperty");
ビューモデルで次のメソッドを定義しました (コード量を減らすためにエラー チェックを削除しました)。
public void RegisterDependencies(string property, params string[] dependencies)
{
foreach (string item in dependencies)
{
IList<string> deps;
if (dependenciesList.TryGetValue(item, out deps))
{
if (!deps.Contains(property))
{
deps.Add(property);
}
}
else
{
deps = new List<string>();
deps.Add(property);
dependenciesList[item] = deps;
}
}
}
PropertyChanged
私のビューモデルは、次の方法でイベントをサブスクライブします。
void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
IList<string> dependencies;
if (dependenciesList.TryGetValue(e.PropertyName, out dependencies))
{
foreach (string item in dependencies)
{
RaisePropertyChangedEvent(item);
}
}
}
これは、プロパティに依存関係があるかどうかを単純にチェックし、依存関係がある場合は、PropertyChanged
それらのイベントも発生させます。これはすべて美しく機能し、これまでのところ非常に良好です。
私が本当に望んでいるのは、文字列ではなくラムダ式を使用して、オートコンプリートとリファクタリングのサポートを改善することです。私が求めているのは次のようなものです:
RegisterDependencies<ViewModelType>(p => p.Property,
p => p.FirstDependency,
p => p.SecondDependency); //and so on...
メソッドのシグネチャを次のように再定義しました。
public void RegisterDependencies<T>(Expression<Func<T, object>> property,
prams Expression<Func<T, object>>[] dependencies)
{
}
現時点では、メソッドは単に式を文字列に変換しようとしていますが、これが私が行き詰まっているところです。式からプロパティの名前を取得して文字列に変換する方法がわかりません。
Josh Smith の MVVM Foundation には、PropertyChangedObserver
これを実行するコードが含まれているというクラスが含まれており、これを例に合わせて適応させようとしました。
private static string GetPropertyName<T>(Expression<Func<T, object>> expression)
{
var lambda = expression as LambdaExpression;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = lambda.Body as UnaryExpression;
memberExpression = unaryExpression.Operand as MemberExpression;
}
else
{
memberExpression = lambda.Body as MemberExpression;
}
return memberExpression != null ? ((PropertyInfo)memberExpression.Member).Name : null;
}
これは私の更新されたRegisterDependencies
メソッドで呼び出されています (これは文字通り、現時点でのメソッドのコード全体です):
string propertyName = GetPropertyName(property);
foreach (Expression<Func<T, object>> expr in dependencies)
{
string dependencyName = GetPropertyName(expr);
}
これを実行すると、XamlParseException
. これは、標準の例外ウィンドウをスローしないため、デバッグが困難です。Visual Studio の出力ウィンドウにはもう少し詳しい情報が表示されます。最初の例外は a のようInvalidCastException
ですが、両方の式が同じ型であるため理由はわかりません。
誰でも光を当てて、これを手伝ってもらえますか?