XAML Constructor Parameter with Binding

I have a custom renderer to display a video player, which takes in one parameter: the URL of the video. It works fine, even in XAML:

  <ui:VideoContentView x:Name="Video">
    <x:Arguments>
      <x:String>
        https://09-lvl3-pdl.vimeocdn.com/01/3604/4/118020995/330937778.mp4?expires=1443633975&amp;token=0002ee6b1e005dc2064f8
      </x:String>
    </x:Arguments>
  </ui:VideoContentView>

But I would like to bind the URL, rather than hard-coding it. The problem is that when I try to bind the argument:

  <ui:VideoContentView x:Name="Video">
    <x:Arguments>
      <x:String>
        {Binding ContentUrl}
      </x:String>
    </x:Arguments>
  </ui:VideoContentView>

...the page does not load. I do not get an error, either.

Is this a bug, or is there something special I should be doing to bind to a constructor parameter?

Best Answer

Answers

  • ChaseFlorellChaseFlorell CAInsider, University mod

    Ha, I was just trying the same thing last week.

  • @adamkemp That makes perfect sense, thank you... the concept of a BindableProperty is a lot clearer now. The reason I was going with a constructor parameter was that I wanted the property to be non-optional, but I suppose a video player without a video should behave just like a Label without a string to display. I've changed the constructor parameter to a property and it's working as expected.

  • TK33TK33 USMember

    @adamkemp said:
    If you think about what you're trying to do and how bindings work then it's obvious why this doesn't work (there are actually several reasons). First, bindings only work on properties of objects. More specifically, it only works on bindable properties of objects. A bindable property is one that has a static BindableProperty instance in the class that tells the binding system how to interact with that property. Even more specifically, you can only use bindable properties for a class that inherits from BindableObject. The binding system interacts with the object by using the methods GetValue and SetValue in the BindableObject class, and the storage for those property values is a private dictionary within that class. The keys for that dictionary are the BindableProperty objects.

    Digging deeper, when an object is created in XAML with bindings it goes through two stages:

    1. Create the object.
    2. Set up the values and bindings.

    The bindings are created by calling SetBinding (another method in BindableObject) so obviously it can only be done after creating the object. Importantly, the bindings are usually created before the BindingContext is set. That means at the time that SetBinding is called to create the bindings the system doesn't know what the values of those properties actually is.

    So with that in mind, think about what you tried here. You're trying to create a binding for a parameter of a constructor. There's no property for that, let alone a bindable property so that can't work. Further, you've trying to use a binding that would have to be created before the object exists, and that's kind of nonsense. And lastly, even if you were to argue that in this case it shouldn't use SetBinding and instead just use the current value from the view model to pass into the constructor it still couldn't do that because it probably still doesn't know what the view model actually is, and thus can't get the current value from it.

    The fix for this is simple: make that thing a property instead of a constructor parameter.

    Hi Adam, I created a post (https://forums.xamarin.com/discussion/85854/data-binding-and-passing-object-to-custom-control#latest) regrading something similar to this. My problem is that the object created in XAML with bindings won't bind to my custom control BindableProperty. I explained in more details on that post. I really could use some help to understand this. Thanks

Sign In or Register to comment.