如何使用WPF从bindingexpression解析绑定对象?

嗨有没有人知道是否有任何内置的类来解决绑定对象的绑定对象及它的DataItem和属性路径?

我正在尝试为文本框编写Blend 3行为,该行为会自动调用绑定到文本框Text属性的对象上的方法。

文本框绑定到viewmodel类的属性。 我想要做的是从绑定表达式解析viewmodel类,然后对此进行调用。

我首先从行为的关联对象中检索绑定表达式,如下所示:

private BindingExpression GetTextBinding() { return this.AssociatedObject.GetBindingExpression(TextBox.TextProperty); } 

完成此操作后,如果我们查看绑定表达式,我们可以看到它通过绑定表达式的DataItem属性引用了数据上下文。

另外,我们有绑定表达式父绑定绑定的属性的相对路径。

所以,我们可以得到这些信息:

 var bindingExpression = GetTextBinding(); object dataContextItem = bindingExpression.DataItem; PropertyPath relativePropertyPath = bindingExpression.ParentBinding.Path; 

现在,这个属性路径可能是一个深度嵌套和复杂的路径,我非常希望避免(重新)实现解析。 我已经搜索了.NET文档并用reflection器围绕组件弹跳,但都无济于事 – 我找不到肯定必须存在的东西 – 必须有一些类来执行数据项目的路径解析(数据上下文)。

有谁知道这可能存在的地方? 有关解决绑定对象的替代方法的任何建议吗?

注意,我正在尝试获取绑定对象的对象绑定属性(在这种情况下为字符串) – 我显然可以轻松获得绑定值,但它是我需要的父级。

在此先感谢您的帮助! 菲尔

下面是一个扩展方法的快速实现,它将完成您正在寻找的内容。 我也找不到任何相关的东西。 如果由于某种原因无法找到该值,则下面的方法将始终返回null。 当路径包含[]时,该方法将不起作用。 我希望这有帮助!

 public static T GetValue(this BindingExpression expression, object dataItem) { if (expression == null || dataItem == null) { return default(T); } string bindingPath = expression.ParentBinding.Path.Path; string[] properties = bindingPath.Split('.'); object currentObject = dataItem; Type currentType = null; for (int i = 0; i < properties.Length; i++) { currentType = currentObject.GetType(); PropertyInfo property = currentType.GetProperty(properties[i]); if (property == null) { currentObject = null; break; } currentObject = property.GetValue(currentObject, null); if (currentObject == null) { break; } } return (T)currentObject; } 

对于将来遇到这个问题的人:

当.NET 4.5可用时,它将在BindingExpression上拥有许多新属性,以大大简化您的需求。

ResolvedSource – 实际绑定的对象,当您拥有像“grandparent.parent.me.Name”这样的绑定源时非​​常有用。 这将返回’我’对象。

ResolvedSourcePropertyName – 绑定到的ResolvedSource上的属性的名称。 在上面的例子中,“名称”。

同样,将有TargetTargetName属性。

使用BindingExpression上的这些辅助属性,您可以使用更简单,更简化的reflection,更有可能在极端情况下(索引器)工作。

仅供参考,PropertyPath解析由名为PropertyPathWorker的内部MS类处理,该类位于MS.Internal.Data下的PresentationFramework中。 如果你在Reflector中打开它,你会发现它非常复杂,所以我不建议尝试复制它的function。 它与整体Binding架构紧密结合。

支持所有属性路径语法的最强大的方法 – 包括附加的依赖项属性和分层遍历 – 可能是创建一个带有DependencyProperty的虚拟DependencyObject。 然后,您可以从“所有者”路径创建绑定到虚拟依赖项属性,创建新的BindingExpression,然后调用表达式的UpdateTarget。 从表面上看,这是一个相当繁重的方式,看起来像一个简单的任务,但我认为在解析绑定属性路径的方式中有很多隐藏的问题。

我相信此处发布的其他StackOverflow 解决方案也可能适合您。

复制代码块供参考,阅读原始post以获取Thomas Levesque提供的更多详细信息。

 public static class PropertyPathHelper { public static object GetValue(object obj, string propertyPath) { Binding binding = new Binding(propertyPath); binding.Mode = BindingMode.OneTime; binding.Source = obj; BindingOperations.SetBinding(_dummy, Dummy.ValueProperty, binding); return _dummy.GetValue(Dummy.ValueProperty); } private static readonly Dummy _dummy = new Dummy(); private class Dummy : DependencyObject { public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(Dummy), new UIPropertyMetadata(null)); } } 

正如Dan Bryant已经指出的那样, PropertyPath解决方案与整体绑定架构紧密结合。
如果你需要与WPF完全相同的分辨率,你应该使用Thomas Levesque对这个问题的回答。

但是,如果你只需要一般的路径分辨率,你可以使用我开发的一个nuget包 Pather.CSharp 。

它基本上类似于zhech的答案,但更复杂。

它的主要方法是Resolve on the Resolver类。 传入目标对象路径作为字符串返回所需的结果。
一个例子:

 IResolver resolver = new Resolver(); var target = new { Property1 = new { Property2 = "value" } }; object result = r.Resolve(target, "Property1.Property2"); 

它还支持通过密钥进行索引或字典访问的 集合访问
这些的示例路径是:

 "ArrayProperty[5]" "DictionaryProperty[Key]"