Get the target element of a binding
- Hi,
I was playing around with the following methods ( BindingOperations.GetBinding()/GetBindingExpression() ) to find both points (source and target) of a binding.
The thing is I need to find the child element that is binded to a parent's dependency property, through the parent element.
If I call these methods from the child element the Binding/BindingExpression object is returned, otherwise, if I try this in the parent element it returns null. I also tried to make the binding TwoWay but it didn't work.
Is there a way to achieve my goal using these or other methods? (Reflection maybe?)- Tipo AlteradoJim Zhou - MSFTModeradorsegunda-feira, 16 de novembro de 2009 8:33custom did not provide feedback in time
- Tipo AlteradoJay Rocha terça-feira, 17 de novembro de 2009 18:09
Respostas
- Well, the first thing that comes to mind, albeit cheesy, is to create an attached property. Something like ExpanderHelpers.ImplementsHeader="true"
If you define that attached property and make the person implementing the template set that on the element that implements the header then you would have a reference to the element.
I call this cheesy, becuase you really don't have anyway to enforce that they set that Attached property. So if you don't control all the templates that approach likley will have issues.
I think your best bet might be to subclass DataTemplate and add some addtional property that has to be set, that tells if the element is the header. Then Subclass your expander (or whatever control you are using) and make it use this sublcassed DataTemplate class. That would enforce that the consumer of your Control would have to use your custom DataTemplate and therefore would have to set that bit on the DataTemplate.
That is a little hokey too but it would work.
This seems like kind of a strange scenario, is there a particular reason you need to access the specific UI element? One of the keys to WPF development is "lookless" controls. Basically meaning that controls can change there visual implementation and code should still work. To make that possible, you almost never want to depend on specific UI structures in your code (as they can break when someone changes the template). This is were databinding comes in to play- Marcado como RespostaJim Zhou - MSFTModeradorsexta-feira, 20 de novembro de 2009 8:06
Todas as Respostas
- I am little confused on what you are asking and without a code sample this might not be what you are looking for but you can reverse the direction of the Binding pipeline by changing the Binding Mode attribute to OneWayToSource.
By doing this you will be sending the Attribute value to your binding target instead of pushing the target value to the Binding Attribute. If you are binding a child element to a parent DP then using OneWayToSource will send the child element to the parent DP.
Hopefully that makes sense, again not sure if it is what you need or not. Could you post a code snippet to help clarify your question? Hi,
I believe I didn't describe my question clearly. Maybe with a simple example it will become easy to understand:Imagine that you have a TextBox and a TextBlock defined like this:
<TextBox x:Name="MyTextBox" Text="SomeText" (...)/>
<TextBlock x:Name="MyTextBlock" Text="{Binding ElementName=MyTextBox, Path=Text}" (...)/>
If I call BindingOperations.GetBinding()/GetBindingExpression() on MyTextBox ( and TextBox.TextProperty), it returns null, but if I call these methods from MyTextBlock (and TexBlock.TextProperty) is returns the binding/BindingExpression with all the binding information.
My doubt is: Is there any way that I can get the binding information through MyTextBox, by using these or other methods?
Sorry if I mislead you with my initial question, I hope this clears the situation.
Notice that this is just an example, my situation concerns a Templated Control. I want to determine which child element presents the content of the element, from the root level parent.- Hi,
-->My doubt is: Is there any way that I can get the binding information through MyTextBox, by using these or other methods?
Why not get the binding information from the binding targer(in this case MyTextBlock)?
-->my situation concerns a Templated Control. I want to determine which child element presents the content of the element, from the root level parent.
Can you provide the code for us to repro?
Thanks.
Sincerely.
Jim Zhou -MSFT - We are changing the issue type to “Comment” because you have not followed up with the necessary information. If you have more time to look at the issue and provide more information, please feel free to change the issue type back to "Question” by clicking the "Options" link at the top of your post, and selecting "Change Type" menu item from the pop menu. If the issue is resolved, we will appreciate it if you can share the solution so that the answer can be found and used by other community members having similar questions.
Thank you!
Jim Zhou -MSFT - Hi Jim,
-->My doubt is: Is there any way that I can get the binding information through MyTextBox, by using these or other methods?
Why not get the binding information from the binding targer(in this case MyTextBlock)?
Answer: Because my objective is to find an element inside the parent's template and not the other way around. The point is not iterating through the parent element's tree to find the child I want, but to get it directly from the root element.
- Hi Jay Rocha,
-->The point is not iterating through the parent element's tree to find the child I want, but to get it directly from the root element.
I am sorry I did not fully understand you, could you kindly provide a sample to demonstrate the issue you are facing? Adding some necessary comments in the code will be better, so that we can quickly repro your scenario based on the sample.
Thanks.
Sincerely.
Jim Zhou -MSFT - Hi Jay,
I understand what you are trying to do but I don't think there is any way to do what you want. This is because of the way databinding works.
When you are bound to and element that source element has no idea that someone else is bound to it's value and listening for property change notifications.
The best I could think would be to override the TextBox and hook into it's property change event for the Text property, when that fires you can determine is anyone is wired up to the change handler but I doubt you will be able to interrogate the subscriber and actually get the data you are looking for. You likely will only be able to determine if someone is listening.
Can you maybe more fully explain the problem you are trying to solve, maybe there is a different way to accomplish what you are trying to do? Hi Jay,
Hi Foo,
I understand what you are trying to do but I don't think there is any way to do what you want. This is because of the way databinding works.
When you are bound to and element that source element has no idea that someone else is bound to it's value and listening for property change notifications.
The best I could think would be to override the TextBox and hook into it's property change event for the Text property, when that fires you can determine is anyone is wired up to the change handler but I doubt you will be able to interrogate the subscriber and actually get the data you are looking for. You likely will only be able to determine if someone is listening.
Can you maybe more fully explain the problem you are trying to solve, maybe there is a different way to accomplish what you are trying to do?
Thanks for your reply. I suspected that this info couldn't be obtained...I just wanted a confirmation because I'm a newbie in WPF.
This is my problem:
Imagine an Expander element (for example) that can have different templates in your application. An example of the template hierarchy of the Expander could look like this:
Expander
Border
DockPanel
ToggleButton (Implements the Header of the Expander)
Border
Grid
Path
ContentPresenter (Content of the Expander's Header)
ContentPresenter (Content of the Expander)
But someone else could have a different template, like for example a DataTemplate for the Header.
I want to find the element that shows the Header(for example) object independently of the expander's ControlTemplate and HeaderTemplate.
My first approach was to try and find the element that is bound to the Header Property of the Expander and then iterate and try to find the element, but this doesn't seem possible.
Any idea on how to do this?- Well, the first thing that comes to mind, albeit cheesy, is to create an attached property. Something like ExpanderHelpers.ImplementsHeader="true"
If you define that attached property and make the person implementing the template set that on the element that implements the header then you would have a reference to the element.
I call this cheesy, becuase you really don't have anyway to enforce that they set that Attached property. So if you don't control all the templates that approach likley will have issues.
I think your best bet might be to subclass DataTemplate and add some addtional property that has to be set, that tells if the element is the header. Then Subclass your expander (or whatever control you are using) and make it use this sublcassed DataTemplate class. That would enforce that the consumer of your Control would have to use your custom DataTemplate and therefore would have to set that bit on the DataTemplate.
That is a little hokey too but it would work.
This seems like kind of a strange scenario, is there a particular reason you need to access the specific UI element? One of the keys to WPF development is "lookless" controls. Basically meaning that controls can change there visual implementation and code should still work. To make that possible, you almost never want to depend on specific UI structures in your code (as they can break when someone changes the template). This is were databinding comes in to play- Marcado como RespostaJim Zhou - MSFTModeradorsexta-feira, 20 de novembro de 2009 8:06
- Hi Foo,
Thanks for your good suggestions, I thought of a attached property also, but the DataTemplate one seems good.
My final goal is to get the visual offset (to the Expander) of the element that shows the Expander's Header String, that's why I wanted to know where (which element) exactly the Header property is displayed.
Do you see a better way to get that value?
Thanks for your answers so far.

