WPF - Getting a property value from a binding path
Asked Answered
S

4

16

if I have an object say called MyObject, which has a property called MyChild, which itself has a property called Name. How can I get the value of that Name property if all I have is a binding path (i.e. "MyChild.Name"), and a reference to MyObject?

MyObject
  -MyChild
    -Name
Sloshy answered 26/8, 2010 at 17:35 Comment(1)
Can you provide an example of how you want to use this?There
P
27

I found a way to do this, but it's quite ugly and probably not very fast... Basically, the idea is to create a binding with the given path and apply it to a property of a dependency object. That way, the binding does all the work of retrieving the value:

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));
    }
}
Prudential answered 26/8, 2010 at 20:35 Comment(5)
That seems like a lot of machinery to get the value of a binding but I can't think of a better general purpose code solution. +1 and Cheers.Welbie
Excellent, thanks Thomas! The reason I need something like this is because I have written a custom markup extension for loading images. This extension has a Name property for the image name, which I now want to bind to a model property in a DataTemplate which uses the markup extension. However, I can't bind because Name isn't a DP, nor can it be :( This was the only solution I could think of, so I will give this code a try. Thanks.Sloshy
This works perfectly for my needs (getting and setting the value of a property of a view model given a binding path). Is there a similar way to get the type of the property that would be bound with a given binding path?Jacquiline
@Wayne, not that I know of. You can get the value using the trick above, and call GetType on it, but of course if the value is null it doesn't work...Prudential
Right, it's the nulls that are the problem. I still need the type in that case too. As for reflection, that logic could be hairy, considering that binding paths can use more than just dot notation for property access (eg. [] for indexing into lists and dictionaries). I was hoping there was some other hidden feature of BindingOperations et. al. that would do it for me. Thanks.Jacquiline
S
4

I developed a nuget package Pather.CSharp that does exactly what you need.

It contains a class Resolver that has a Resolve method which behaves like @ThomasLevesque's GetValue method.
Example:

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"

It even supports collection access via index or dictionary access via key.
Example paths for these are:

"ArrayProperty[5]"
"DictionaryProperty[Key]"
Shotgun answered 30/12, 2015 at 22:9 Comment(2)
Does it support accessing explicitly implemented interface properties and hidden properties?Delanty
@Delanty Yes. It works via reflection, so if the property exists on the object and is public, it will get its value.Shotgun
H
0

not sure what you want to do but and how (xaml or code) yet you can always name your object

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

an then use it in code

myBindingObject.Something.Name

or in xaml

<BeginStoryboard>
 <Storyboard>
    <DoubleAnimation
        Storyboard.TargetName="myBindingObject"
        Storyboard.TargetProperty="Background"
        To="AA2343434" Duration="0:0:2" >
    </DoubleAnimation>
 </Storyboard>
</BeginStoryboard>
Hour answered 26/8, 2010 at 17:45 Comment(0)
C
0

I am doing it this way. Please let me know if this is a terrible idea, as C# is just a side job for me so I am not an expert objectToAddTo is of type 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
Carmon answered 5/2, 2018 at 13:14 Comment(1)
This can work if the binding path is a simple property name. It does not work if the path is something like "Dictonary[key]" or "Owner.Member".Navaho

© 2022 - 2024 — McMap. All rights reserved.