我正在为我的 WPF viewModel 基类编写一个小扩展,它允许我以比在 getter 中引发多个PropertyChanged
事件的标准方法更简洁的方式定义属性之间的依赖关系:
所以而不是:
public int ThisProperty
{
get
{
thisProperty = value;
RaisePropertyChangedEvent("ThisProperty");
RaisePropertyChangedEvent("FirstDependentProperty");
RaisePropertyChangedEvent("SecondDependentProperty");
}
}
我希望能够在我的 ViewModels 构造函数中做这样的事情:
RegisterDependencies("This Property",
"FirstDependentProperty", "SecondDependentProperty");
我在 viewModel 中定义了以下方法(删除了错误检查以减少代码量):
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
也会为这些属性引发事件。这一切都很好,到目前为止一切都很好。
我真正想要的是使用 lambda 表达式而不是字符串,以便我获得自动完成和更好的重构支持。我所追求的是这样的:
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 的输出窗口提供了更多信息,似乎最初的异常是 aInvalidCastException
虽然我不确定为什么因为两个表达式属于同一类型。
任何人都可以阐明并帮助我吗?