How to do the equivalent of {Binding Source} in code? RRS feed

  • Question

  • User184099 posted

    I'm extending a control to be able to reuse it across my current Xamarin project. As part of this control, I need to create a DataTemplate programmatically. I have this part figured out and it works ok.

    The DataTemplate has a Label in it. I need to bind the Label's BindingContext property to {Binding Source}. I need to bind the Label's Text property to {Binding Path=Name}.

    This works in XAML, but I don't want to have to copy it to a million different places in the code base. <dxGrid:TemplateColumn FieldName="MyPropertyName" Caption="MyColumn"> <dxGrid:TemplateColumn.DisplayTemplate> <DataTemplate> <Label BindingContext="{Binding Source}" Text="{Binding Source, Path=MyPropertyName}" /> </DataTemplate> </dxGrid:TemplateColumn.DisplayTemplate>

    My extended control looks like this right now: `public class MyColumn : TemplateColumn { public MyColumn() { DataTemplate displayTemplate = new DataTemplate(() => { BindingBase textBinding = new Binding(FieldName);

                Label label = new Label();
                // TODO: Bind BindingContextProperty to {Binding Source}
                //label.SetBinding(BindingContextProperty, binding);
                label.SetBinding(Label.TextProperty, textBinding);
                return new ViewCell
                    View = label
            DisplayTemplate = displayTemplate;

    I'm getting hung up in the binding because I'm not sure how to do the equivalent of {Binding Source} in code. Any help would be appreciated.

    This question was originally posted to StackOverflow here: http://stackoverflow.com/questions/35808706/how-to-do-the-equivalent-of-binding-source-in-code

    Saturday, March 5, 2016 11:28 PM

All replies

  • User76916 posted

    @TC2254 - binding should be the same as any other control. By default the control will get the BindingContext of its parent. Below should be the equivalent of BindingContext={Binding Source} but are you getting an error or something using the below?

    label.SetBinding(Label.BindingContextProperty, Source);

    Sunday, March 6, 2016 12:47 AM
  • User184099 posted

    @AdamP Thanks for the response. Unfortunately this does not work as there is no "Source" property on the TemplateColumn. If I set it to a string "Source", then it fails with a Null Reference Exception. I made another pass at it this morning and got it working this way:

    public MyColumn()
        DataTemplate displayTemplate = new DataTemplate(() =>
            Grid grid = new Grid();
            grid.SetBinding(Grid.BindingContextProperty, "Source");
            Label label = new Label();
            return grid;
        this.DisplayTemplate = displayTemplate;
    Monday, March 7, 2016 5:36 PM
  • User76916 posted

    @TC2254 - glad you managed to get it working. Apologies, I missed the fact it was in a DataTemplate.

    Monday, March 7, 2016 10:22 PM
  • User248484 posted

    Is there also any way to perform GetBinding? I want to get the actual Binding (i.e. the property name), not the value. Anyone?

    Monday, July 24, 2017 6:32 AM
  • User124403 posted

    @ShimmyWeitzhandler - Neither BindingContext nor BindableObject have any methods that would help you search for a binding, so I believe the answer is "No". AFAIK, you would have to create the bindings in code (not XAML), and create your own association (dictionary) between views (or viewmodels?) and binding names. Maybe you can create and cache the BindableProperties involved in the bindings?

    Friday, December 22, 2017 11:25 PM
  • User308156 posted

    @"SteveShaw.5557" - You actually CAN create a binding in XAML and use it later. It can be cached in the resource dictionary (which I recommend if you are switching bindings at runtime) or created in place. Here is a simple example:

    <Binding x:Key="MyKeyIfInResDic" Path="The.Property" Converter="{StaticResource MyStaticConverter}" />

    If you are following the MVVM principles, no ViewModel should ever have to bother with creating/setting/caching bindings, if you'd ask me.

    Thursday, November 22, 2018 5:46 PM
  • User124403 posted

    @GaetanF - that is useful to know, thanks.

    Given that, the answer to Shimmy, is to go about it a different way. While AFAIK it isn't possible to do what he asked, if the goal is to be able to switch between bindings, then instead of trying to access property names, using resources and their names is a good solution.

    The way I read his question, he was trying to get information (in code behind) about the DependencyProperty that was attached to a binding, once a BindingContext was attached. He asked for a GetBinding equivalent to SetBinding - BindableObject.SetBinding(BindableProperty, BindingBase). Or perhaps a BindableObjectExtensions.SetBinding method that takes a string.

    What you suggest is much cleaner (if it solves the need). You have resource objects, each of which is a System.Windows.Data.Binding. Set a UI property to one of those at runtime, and let internal code hook that up to the DependencyProperty described by Binding's Path.

    To attach to a different DependencyProperty, use a binding with a different path (or change the path property of the binding?)

    It isn't GetBinding functionality, but it allows some interesting "Set" scenarios.

    This raises a question I don't know the answer to:

    Could GetBinding be approximated this way:

    • Code-behind gets value of some UI property, as defined in XAML.
    • Determine that the UI property has an attached binding.
    • If so, get Path property of that binding.
    • Later, to set the UI property back to that same binding, pass that path as a parameter to SetBinding.

    If this is possible, what would the code for those steps look like?

    (To keep it simple, NOT inside of a DataTemplate, which is what TC2254 asked about.)

    I don't have a reason to test this right now, but something like this?

    <Label x:Name="myLabel" Text="{Binding MyText}">

    in code-behind:

    // ... not quite right ...
    var prop = myLabel.TextProperty;   // type is BindableProperty
    var binding = ?? how get attached binding, if any ??
    string path = binding.Path;   // "MyText"?
    // Set myLabel's Text to something else...
    // Later, to restore original binding.
    myLabel.SetBinding(Label.TextProperty, path);

    NOTE: I'm not suggesting this is a good idea, even if possible. Just exploring the limits of what is possible, to better understand working with XAML.

    Friday, March 22, 2019 4:58 PM