Forum Xamarin.Forms

Binding within a ControlTemplate

tyjentyjen USMember ✭✭

I can't for the life of me get binding to work as expected when using a ControlTemplate.

I've simplified my code for example purposes, but the overall structure is the same.

I have a ControlTemplate defined in App.xaml like so:

<ControlTemplate x:Key="MyControlTemplate">
    <ContentView>
        <Label Text="{Binding Name}" />
    </ContentView>
</ControlTemplate>

I'm using this template within a page like so:

<TemplatedView ControlTemplate="{StaticResource MyControlTemplate}" />

Assuming my page's ViewModel has an object in it called Person, and the Person object has a property called Name

How do I properly hook up the binding? Nothing seems to work. I've tried every combination I can think of, for example...

  • Binding the BindingContext of the TemplatedView to the Person object in the ViewModel
  • Using TemplateBinding instead of Binding
  • Setting the Source property of the label text binding in the control template to Person
  • Binding to Person.Name
  • Binding to Parent.Person.Name
  • Setting all of these bindings in code as opposed to in XAML
  • Binding BindingContext.Name within the template

There is almost no documentation online about ControlTemplate's, and Xamarin's only reference isn't sufficient for real-world scenarios. I also don't get any error messages about binding when using Binding, but I do when I use TemplateBinding. They aren't useful though, just complains that the 'Name' property doesn't exist on Person, which it does.

Any advice here?

Posts

  • RenaudLaloireRenaudLaloire BEUniversity ✭✭

    BindingContext="{TemplateBinding BindingContext}" should not be necessary but it seems that the BindingContext is not automatically transferred to the children of the ControlTemplate (like it is in WPF) ... I guess this is a Xamarin.Forms bug.

  • batmacibatmaci DEMember ✭✭✭✭✭

    what is the TemplatedView ? how is it different than using contentview?

  • zuckerthobenzuckerthoben USMember ✭✭
    edited June 2017

    I tried this, but cant get it to work.

    Here is my Template in App.xaml:

    <ResourceDictionary>
            <ControlTemplate x:Key="MainPageTemplate">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="100" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
    
                    <BoxView BackgroundColor="#0054a1" />
                    <Button BindingContext="{TemplateBinding BindingContext}" HorizontalOptions="Start" Text="Back" 
    IsVisible="{TemplateBinding BindingContext.IsBackButtonVisible}" VerticalOptions="Center" Margin="20,0" 
    Command="{TemplateBinding BindingContext.BackCommand}" />
                    <Label BindingContext="{TemplateBinding BindingContext}" TextColor="White" Text="{TemplateBinding 
    BindingContext.PageTitle}" VerticalOptions="Center" HorizontalOptions="Center" FontSize="Large" />
                    <ContentPresenter VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Grid.Row="1" />
                </Grid>
            </ControlTemplate>
    </ResourceDictionary>
    

    Here is my View:

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:Roomplan.ViewModels"
             x:Name="MainPage"
             x:Class="Roomplan.MainPage">
    <ContentPage.BindingContext>
        <vm:MainViewModel x:Name="viewModel" />
    </ContentPage.BindingContext>
    <ContentView ControlTemplate="{StaticResource MainPageTemplate}">
        <ContentView.Content>
            <ScrollView>
                <ListView IsPullToRefreshEnabled="True" RefreshCommand="{Binding ListRefreshCommand}" ItemsSource="
     {Binding Sites}">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <StackLayout Orientation="Vertical">
                                    <Label Text="{Binding FriendlyName}" />
                                    <Button Text="{Binding Name}"
                                            HorizontalOptions="Center"
                                            VerticalOptions="Center"
                                            Command="{Binding Path=BindingContext.RoomClickCommand,
                                            Source={x:Reference MainPage}}" CommandParameter="{Binding Name}" />
                                    <Label Text="{Binding Description}" />
                                </StackLayout>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </ScrollView>
        </ContentView.Content>
    </ContentView>
    </ContentPage>
    

    And here is my (most parts omitted) ViewModel:

    public class MainViewModel : BaseViewModel, IRoomPlanViewModel
    {
        public string PageTitle
        {
            get => "Raumplanung";
        }
    
        public bool IsBackButtonVisible
        {
            get => false;
        }
    }
    

    Why is it not working?

  • MarlonRibeiroMarlonRibeiro USMember ✭✭✭

    @zuckerthoben Exactly the same issue here! Did you find a solution?

  • eliblack1eliblack1 Member ✭✭

    For anyone running across this in 2019: It looks like the BindingContext="{TemplateBinding BindingContext}" part is no longer necessary for this to work.

Sign In or Register to comment.