Xaml is using hidden property?

LeloLelo ✭✭✭Member ✭✭✭
edited June 13 in Xamarin.Forms

I have declared a property in a custom control called X that hides VisualElement.X property. Visual studio tells me I can use the new keyword if the hiding was intended - which it is:

public new double X
{
    get { return 0; }
    set { Console.WriteLine("I was not called with: " + value); }
}

When using the control in xaml - setting the X to something. The set is not called. Instead the VisualElement.X property is called - which throws an exception. Why is not the property I declared in the custom control used instead?

I also asked this on stackoverflow

Answers

  • AdamMeaneyAdamMeaney ✭✭✭✭✭ USMember ✭✭✭✭✭

    It needs to be a BindableProperty if it is on a control. They are using the https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.visualelement.xproperty?view=xamarin-forms field using some reflection stuff for Bindings in XAML.

    So you need your own BindableProperty field to do Bindings correctly.

  • LeloLelo ✭✭✭ Member ✭✭✭

    @AdamMeaney said:
    It needs to be a BindableProperty if it is on a control. They are using the https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.visualelement.xproperty?view=xamarin-forms field using some reflection stuff for Bindings in XAML.

    So you need your own BindableProperty field to do Bindings correctly.

    I have noticed I can declare a property - that does not exist in parent :

    public double AnotherX
    {
        get { return 0; }
        set { Console.WriteLine("Was called with: " + value); }
    }
    

    And that setter is called.
    How come the BindableProperty is needed when hiding a property. Does xaml look for BindableProperty declarations first - and then for "normal" properties -afterwards?

  • AdamMeaneyAdamMeaney ✭✭✭✭✭ USMember ✭✭✭✭✭

    I am not too familiar with the internals of the Xaml parsing, but I wouldn't be surprised. That's a pretty reasonable optimization to try and use the BindableProperties first, as that is what every property on a control should be.

  • LeloLelo ✭✭✭ Member ✭✭✭
    edited June 13

    But in this situation the BindableProperty ends up hiding a distant child property.

    I was hoping I could use [observable] properties in my custom control with MobX instead of using BindableProperties.

  • AdamMeaneyAdamMeaney ✭✭✭✭✭ USMember ✭✭✭✭✭

    If you have to manually define a bunch of properties anyway, you could always define an ObservableX property or something that you bind the X property to .

  • LeloLelo ✭✭✭ Member ✭✭✭

    @AdamMeaney said:
    If you have to manually define a bunch of properties anyway, you could always define an ObservableX property or something that you bind the X property to .

    Yes the following can be done:

    public class MyCustomControl : ContentView // distant child of VisualElement
    {
        public MyCustomControl()
        {
            SetBinding(WidthRequestProperty, new Binding(path: "MyX", mode: BindingMode.TwoWay, source: this)); // can't set XProperty
        }
        public double MyX
        {
            get { return 0; }
            set { Console.WriteLine("I was set with: " + value); }
        }
    }
    

    XProperty can't be set though - because it is readonly/has a private setter:
    from VisualElement:

    public double WidthRequest
    {
        get { return (double)GetValue(WidthRequestProperty); }
        set { SetValue(WidthRequestProperty, value); }
    }
    
    public double X
    {
        get { return _mockX == -1 ? (double)GetValue(XProperty) : _mockX; }
        private set { SetValue(XPropertyKey, value); }
    }
    
  • AdamMeaneyAdamMeaney ✭✭✭✭✭ USMember ✭✭✭✭✭

    I would assume your code would be binding the other way in that case. Your X gets set from standard X, as that is not something you can change on a control.

    You are trying to Bind X to YourX. Just flip it around.

    If you are looking to change X, you need to figure out how that is done and write that into the PropertyChanged of YourX.

  • LeloLelo ✭✭✭ Member ✭✭✭
    edited June 13

    Yes the only way seem to be to create a BindableProperty, that will hide the VisualElement.XProperty and use PropertyChanged.

Sign In or Register to comment.