Forum Xamarin.Forms

How to set a property of a control in ControlTemplate

In Xamarin Forms: If I have a ControlTemplate like this:

<ContentView.ControlTemplate>
    <ControlTemplate>
        <Grid Margin="0" Padding="0">
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
            </Grid.RowDefinitions>
            <Entry x:Name="ThisEntry1"/>
            <!--Some other Entries-->
                </Grid>
    </ControlTemplate>
</ContentView.ControlTemplate>

Then I used this ControlTemplate in a ContentPage like this:

Wrong Code:

<ContentPage.Content>
    <FlexLayout>
        <entry:MyEntryFromThatTemplage
            Text="???" <<< How to retreive ThisEntry1 and set its Text property here?
                />

In https: // docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/control-templates/creating I can get the Entry this set its Text at runtime using GetTemplateChild("ThisEntry1") but I want to get it in XAML

Best Answer

Answers

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    you have to create a custom property

    https://xamarinhelp.com/xamarin-forms-user-control/

  • tareksalah43tareksalah43 Member ✭✭

    @AlessandroCaliaro said:
    you have to create a custom property

    https://xamarinhelp.com/xamarin-forms-user-control/

    Thank you, but, No. I do not want to copy all the properties of the Entry in my ControlTemplate using BindableProperty. I want to access the Entry by its name in XAML.

  • LandLuLandLu Member, Xamarin Team Xamurai

    It seems this name can only be recognized after OnApplyTemplate. So you can't retrieve it in the XAML.
    However, if you want to get the text of the ThisEntry1 outside of the contentview you can use binding.
    Firstly, define a property for binding in the view model:

    string entryText;
    public string EntryText
    {
        set
        {
            entryText = value;
            onPropertyChanged();
        }
        get => entryText;
    }
    

    Then bind the text of ThisEntry1 to this property like:

    <ContentView.ControlTemplate>
        <ControlTemplate>
            <Grid x:Name="ParentGrid" Margin="0" Padding="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="30"/>
                </Grid.RowDefinitions>
                <Entry x:Name="ThisEntry1" Text="{Binding Parent.BindingContext.EntryText, Source={x:Reference ParentGrid}}"/>
                <!--Some other Entries-->
            </Grid>
        </ControlTemplate>
    </ContentView.ControlTemplate>
    

    I named the Grid here ParentGrid so that its parent is the content view. And we could get the binding context through the parent content view.
    After doing this the text has been bound to the property. We only need to bind the new entry to this property to obtain the value:

    <entry:MyEntryFromThatTemplage Text="{Binding EntryText}"/>
    

    At last, do not forget to assign the binding context of the page.

  • tareksalah43tareksalah43 Member ✭✭

    @LandLu said:
    It seems this name can only be recognized after OnApplyTemplate. So you can't retrieve it in the XAML.
    However, if you want to get the text of the ThisEntry1 outside of the contentview you can use binding.
    Firstly, define a property for binding in the view model:

    string entryText;
    public string EntryText
    {
        set
        {
            entryText = value;
            onPropertyChanged();
        }
        get => entryText;
    }
    

    Then bind the text of ThisEntry1 to this property like:

    <ContentView.ControlTemplate>
        <ControlTemplate>
            <Grid x:Name="ParentGrid" Margin="0" Padding="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="30"/>
                </Grid.RowDefinitions>
                <Entry x:Name="ThisEntry1" Text="{Binding Parent.BindingContext.EntryText, Source={x:Reference ParentGrid}}"/>
                
            </Grid>
        </ControlTemplate>
    </ContentView.ControlTemplate>
    

    I named the Grid here ParentGrid so that its parent is the content view. And we could get the binding context through the parent content view.
    After doing this the text has been bound to the property. We only need to bind the new entry to this property to obtain the value:

    <entry:MyEntryFromThatTemplage Text="{Binding EntryText}"/>
    

    At last, do not forget to assign the binding context of the page.

    Thank you, but this is not the best for me.

    What I want is to access any property of any control in the ControlTemplatew using XAML only referencing its Name or I hope its Type as well.

    Why:

    • I think that the ControlTemplate will have so many controls. Many of them are Entry controls, others are Labels, … etc. If I have to define the properties of each control to set its value when I use it, it will be:
      • To much unnecessary work
      • What if a new version of Xamarin adds a new property to that control as a new feature. Then I have to go for each control and define it.
      • I think I should define only new properties that I want to add as customization to existing control or a behavior to it or to the whole template, not to redefine the same controls to get access to them.

    If it is not possible please tell me and it will best answer to me.

Sign In or Register to comment.