Mattia Durli
Mattia Durli

Reputation: 767

Prism and Control Templates

I'm trying to rewrite the sample "SimpleThemeWithTemplateBinding" that uses ControlTemplates, with Prism. I also added a simple

 HeaderText = "changed";

in the button to change the HeaderText in the ControlTemplate, and it works, in the original sample.

So I copied the template in my app.xaml:

<ControlTemplate x:Key="TealTemplate">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="0.1*" />
                        <RowDefinition Height="0.8*" />
                        <RowDefinition Height="0.1*" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="0.05*" />
                        <ColumnDefinition Width="0.95*" />
                    </Grid.ColumnDefinitions>
                    <BoxView Grid.ColumnSpan="2" Color="Teal" />
                    <Label Grid.Column="1" Text="{TemplateBinding BindingContext.HeaderText}" TextColor="White" VerticalOptions="Center" />
                    <ContentPresenter Grid.Row="1" Grid.ColumnSpan="2" />
                    <BoxView Grid.Row="2" Grid.ColumnSpan="2" Color="Teal" />
                    <Label Grid.Row="2" Grid.Column="1" Text="(c) Xamarin 2016" TextColor="White" VerticalOptions="Center" />
                </Grid>
            </ControlTemplate>

and just changed {TemplateBinding HeaderText} to {TemplateBinding BindingContext.HeaderText}

VIEW:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="TestAppNSPrism7.Views.PrismContentPage9">
    <ContentPage.Content>
        <ContentView x:Name="contentView" Padding="0,0,0,0" ControlTemplate="{StaticResource TealTemplate}" >
            <StackLayout>
                <Label Text="Welcome to Xamarin.Forms! page1"
                       VerticalOptions="CenterAndExpand" 
                       HorizontalOptions="CenterAndExpand" />
                <Label Text="Buazz"
                       VerticalOptions="CenterAndExpand" 
                       HorizontalOptions="CenterAndExpand" />
                <Button Command="{Binding ButtonChangeValueCommand}" Text="Change value" ></Button>
            </StackLayout>
        </ContentView>
    </ContentPage.Content>
</ContentPage>

VIEWMODEL:

public class PrismContentPage9ViewModel : ViewModelBase
        {

            ControlTemplate tealTemplate;

            private string _headerText = "test";
            public string HeaderText
            {
                get
                {               
                    return _headerText;
                }
                set { SetProperty(ref _headerText, value); }
            }      

            public PrismContentPage9ViewModel(INavigationService navigationService) : base(navigationService)
            {
                tealTemplate = (ControlTemplate)Application.Current.Resources["TealTemplate"];           
            }

            private DelegateCommand _buttonChangeValueCommand;
            public DelegateCommand ButtonChangeValueCommand =>
                _buttonChangeValueCommand ?? (_buttonChangeValueCommand = new DelegateCommand(ExecuteButtonChangeValueCommand));

            void ExecuteButtonChangeValueCommand()
            {
                HeaderText = "changed";
            }
        }

The Page gets loaded correctly, with the ControlTemplate, and the HeaderText is "test". So it seems the HeaderText binding with the ControlTemplate is working. But when I set the HeaderText to "changed", the Label doesn't get updated. I debugged and checked that once I press the button it goes through ExecuteButtonChangeValueCommand() and SetProperty(ref _headerText, value)

Any suggestion?

Thanks!

Upvotes: 3

Views: 503

Answers (1)

Iain Smith
Iain Smith

Reputation: 9703

I changed the TemplateBinding from :

Text="{TemplateBinding BindingContext.HeaderText}"

to:

Text="{TemplateBinding Parent.BindingContext.HeaderText}"

and it updates now when I press your changed button.

I believe its due to the template not having a binding context automatically set but the template's parent (PrismContentPage9) has its BindingContext auto-wired from Prism's AutowireViewModel property, e.g.,

prism:ViewModelLocator.AutowireViewModel="True"

Let me know if that works for you.

Upvotes: 1

Related Questions