WPF - 从绑定路径中获取属性值

16
如果我有一个名为MyObject的对象,它有一个名为MyChild的属性,而这个属性本身又有一个名为Name的属性。如果我只有一个绑定路径(例如"MyChild.Name"),以及对MyObject的引用,如何获取该Name属性的值?
MyObject
  -MyChild
    -Name

你能提供一个你想要如何使用它的例子吗? - Rachel
4个回答

27

我找到了一种方法来实现这个,但它相当丑陋,而且可能不是很快...基本上,想法是创建一个与给定路径绑定并将其应用于依赖对象的属性。这样,绑定就可以完成检索值的所有工作:

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));
    }
}

这似乎是很多机械操作来获取绑定值,但我想不出更好的通用代码解决方案。+1 和干杯。 - Berryl
太好了,谢谢Thomas!我需要这样的东西的原因是因为我编写了一个自定义标记扩展来加载图像。该扩展具有用于图像名称的Name属性,现在我想将其绑定到使用标记扩展的DataTemplate中的模型属性。但是,我无法绑定,因为Name不是DP,也不能是:(这是我能想到的唯一解决方案,所以我会尝试这段代码。谢谢。 - devdigital
这对我的需求非常完美(获取和设置视图模型属性的值,给定绑定路径)。是否有类似的方法可以获取与给定绑定路径绑定的属性的类型? - lesscode
@Wayne,据我所知没有这样的方法。您可以使用上面的技巧获取该值,并对其调用GetType,但是如果该值为空,则无法正常工作... - Thomas Levesque
没错,问题就在于空值。即使是在这种情况下,我仍然需要类型。至于反射,考虑到绑定路径可以使用更多的方式来访问属性(例如,[]用于索引列表和字典),那么这个逻辑可能会变得复杂。我希望有一些BindingOperations等隐藏功能可以为我完成它。谢谢。 - lesscode

4
我开发了一个 nuget包 Pather.CSharp,它正好满足你的需求。
它包含一个名为 Resolver 的类,该类具有一个 Resolve 方法,其行为类似于 @ThomasLevesque 的 GetValue 方法。
示例:
IResolver resolver = new Resolver(); 
var o = new { Property1 = Property2 = "value" } }; 
var path = "Property1.Property2";    
object result = r.Resolve(o, path); //the result is the string "value"

它甚至支持通过索引进行集合访问或通过键进行字典访问
这些的示例路径如下:

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

它是否支持访问明确定义的接口属性和隐藏属性? - Grx70
@Grx70 是的。它通过反射工作,因此如果属性存在于对象上并且是公共的,它将获取其值。 - Domysee

0

我是这样做的。如果这是一个可怕的想法,请告诉我,因为C#只是我的副业,所以我不是专家。objectToAddTo的类型是ItemsControl:

BindingExpression itemsSourceExpression = GetaBindingExression(objectToAddTo);
object itemsSourceObject = (object)itemsSourceExpression.ResolvedSource;
string itemSourceProperty = itemsSourceExpression.ResolvedSourcePropertyName;

object propertyValue = itemsSourceObject.GetType().GetProperty(itemSourceProperty).GetGetMethod().Invoke(itemsSourceObject, null); // Get the value of the property

如果绑定路径是一个简单的属性名,那么这可以工作。但如果路径是类似于“Dictionary[key]”或“Owner.Member”的东西,则无法工作。 - Tony Pulokas

0

不确定你想做什么以及如何(XAML还是代码),但你总可以给你的对象命名。

<MyObject x:Name="myBindingObject" ... />

然后在代码中使用它

myBindingObject.Something.Name

或者在XAML中

<BeginStoryboard>
 <Storyboard>
    <DoubleAnimation
        Storyboard.TargetName="myBindingObject"
        Storyboard.TargetProperty="Background"
        To="AA2343434" Duration="0:0:2" >
    </DoubleAnimation>
 </Storyboard>
</BeginStoryboard>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接