Formular una preguntaFormular una pregunta
 

RespondidaGet the target element of a binding

  • sábado, 07 de noviembre de 2009 23:41Jay Rocha Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    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 cambiadoJim Zhou - MSFTModeradorlunes, 16 de noviembre de 2009 8:33custom did not provide feedback in time
    • Tipo cambiadoJay Rocha martes, 17 de noviembre de 2009 18:09
    •  

Respuestas

  • jueves, 19 de noviembre de 2009 17:03Foovanadil Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     Respondida
    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

Todas las respuestas

  • domingo, 08 de noviembre de 2009 22:24Foovanadil Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    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?
  • lunes, 09 de noviembre de 2009 10:44Jay Rocha Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     

    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.

  • viernes, 13 de noviembre de 2009 10:21Jim Zhou - MSFTModeradorMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    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
  • lunes, 16 de noviembre de 2009 8:32Jim Zhou - MSFTModeradorMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    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
  • martes, 17 de noviembre de 2009 18:05Jay Rocha Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    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.

  • miércoles, 18 de noviembre de 2009 9:08Jim Zhou - MSFTModeradorMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    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
  • jueves, 19 de noviembre de 2009 1:39Foovanadil Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    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?
  • jueves, 19 de noviembre de 2009 11:30Jay Rocha Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    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 Foo,

    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?
  • jueves, 19 de noviembre de 2009 17:03Foovanadil Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     Respondida
    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

  • viernes, 20 de noviembre de 2009 9:49Jay Rocha Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    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.