Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve bound object from bindingexpression with WPF?

Hi does anyone know if there are any inbuilt classes for resolving a bound object from a bindingexpression and it's DataItem and property path?

I'm attempting to write a Blend 3 behavior for textboxes which automatically invokes methods on an object bound to the textbox Text property.

The textbox is bound to a property on a viewmodel class. What I want to do is resolve the viewmodel class from the binding expression and then make calls on this.

I first retrieve the binding expression from the behavior's associated object like so:

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

Having done this, if we look at the binding expression, we can see it has a reference to the data context via the binding expression's DataItem property.

In addition, we have the relative path of the property which is bound on the binding expression's parent binding.

So, we can get this information:

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

Now, this property path could potentially be a deeply nested and complex path, which I would very much like to avoid having to (re?)implement resolution of. I've searched around the .NET documentation and bounced around the assemblies with reflector, all to no avail - I can't find what surely must exist - there's got to be some class which performs the resolution of the path for the dataitem (the data context).

Does anyone know where this might exist? Any suggestions for alternative ways of resolving the bound object?

Note, I'm trying to get at the bound object which is the parent of the bound property (the string in this case) - I can obviously easily get at the bound value, but it's the parent I need.

Thanks in advance for any help! Phil

like image 749
Phil Avatar asked Oct 11 '09 03:10

Phil


People also ask

How binding happens in WPF?

Data binding in Windows Presentation Foundation (WPF) provides a simple and consistent way for apps to present and interact with data. Elements can be bound to data from different kinds of data sources in the form of . NET objects and XML.

What is binding source in WPF?

A binding source is usually a property on an object so you need to provide both the data source object and the data source property in your binding XAML. In the above example the ElementName attribute signifies that you want data from another element on the page and the Path signifies the appropriate property.

What is path binding WPF?

Binding path syntax. Use the Path property to specify the source value you want to bind to: In the simplest case, the Path property value is the name of the property of the source object to use for the binding, such as Path=PropertyName . Subproperties of a property can be specified by a similar syntax as in C#.

What are the types of binding in WPF?

Datacontext binding Property Binding with change notification from source Property Binding with change notification from client FallBack value Element Binding Binding with Converter Datacontext binding If any other source is not specified for data bindings then WPF by default searches the data Context.


2 Answers

For people in the future who stumble on this question:

When .NET 4.5 becomes available it will have a number of new properties on the BindingExpression to greatly simplify what you are looking for.

ResolvedSource - The object that is actually being bound to, helpful when you have a binding source like 'grandparent.parent.me.Name'. This would return the 'me' object.

ResolvedSourcePropertyName - The name of the property on the ResolvedSource that is bound to. In the case above, "Name".

Similarly, there will be Target, and TargetName properties.

With these helper properties on BindingExpression you could use some shorter and much more simplified reflection that is more likely to work in extreme situations (indexers).

like image 73
Kevin Kalitowski Avatar answered Sep 21 '22 21:09

Kevin Kalitowski


Below is a quick implementation for an extension method that will do just what you are looking for. I couldn't find anything related to this either. The method below will always return null if for some reason the value cannot be found. The method won't work when the path includes []. I hope this helps!

public static T GetValue<T>(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; } 
like image 32
zhech Avatar answered Sep 21 '22 21:09

zhech