xamlmauiprecompilecompiled-bindings

Can a child control inherit Compiled Binding from a parent view?


I have a child Control that is shared among multiple Content Views, each with a different ViewModel. For example,

<Picker 
     x:Class="...Controls.SharedPicker1"
            Title="Select Item"
            ItemsSource="{Binding Items}"
            SelectedItem="{Binding SelectedItem}"
            ItemDisplayBinding="{Binding ItemName} />

View one:

<ContentView
         x:Class="...ViewOne"
         x:DataType="vms:ViewModelOne">
    <Controls:SharedPicker1 />
</ContentView>

View two:

<ContentView
         x:Class="...ViewTwo"
         x:DataType="vms:ViewModelTwo">
    <Controls:SharedPicker1 />
</ContentView>

The shared Control still produce the following warning:

Binding could be compiled to improve runtime performance if x:DataType is specified.

I also tried to pass the x:DataType directly but found no difference:

<ContentView
         x:Class="...ViewTwo">
    <Controls:SharedPicker1 x:DataType="vms:ViewModelTwo" />
</ContentView>

Does Compile Binding still play any role at this point with such parent child structure regardless of the warning message?


Solution

  • In your examples, you set x:DataType, but it's already implied when BindingContext is set. As a best practice, I encourage developers to only set x:DataType when they're also explicitly setting the BindingContext and to consider doing that in XAML so that x:DataType and BindingContext always comes in pairs.

    In your case, the implementation of SharedPicker1 is not a standalone definition, as the bindings within it can be manipulated at runtime—since the BindingContext can be set externally. To address this, I would suggest adding BindableProperty fields to SharedPicker1 and setting its BindingContext to itself. For example:

    public class SharedPicker1 : Picker
    {
        public static readonly BindableProperty ItemsProperty = ...
        public static readonly BindableProperty SelectedItemProperty = ...
        public static readonly BindableProperty ItemNameProperty = ...
    };
    
    <Picker 
        x:Class="...Controls.SharedPicker1"
        x:Name="this"
        Title="Select Item"
        ItemsSource="{Binding Items, x:DataType=controlnamespace:SharedPicker1, Source={Reference this}}"
        SelectedItem="{Binding SelectedItem, x:DataType=controlnamespace:SharedPicker1, Source={Reference this}}"
        ItemDisplayBinding="{Binding ItemName, x:DataType=controlnamespace:SharedPicker1, Source={Reference this}} />
    

    Then, when you use this component in ViewOne and ViewTwo, you can bind to these new properties and you can set the x:DataType and BindingContext to your ViewModelOne, ViewModelTwo without any issues.