Forum Xamarin.Forms

How to change a label's text of a ControlTemplate in a page which use the template?

The template is

<ControlTemplate x:Key="LabelTemplate"> <StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Padding="0" Margin="0" Spacing="0"> <Label x:Name="lblUsername" Text="show user name here" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" VerticalOptions="Start" HorizontalOptions="FillAndExpand" Font="20" TextColor="White" BackgroundColor="Green" /> <ContentPresenter> </ContentPresenter> </StackLayout> </ControlTemplate>

A content page which use this template can't find the label, lblUsername

<?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:local="clr-namespace:EUser;assembly=EUser" x:Class="EUser.MyTemplatedPage" ControlTemplate="{StaticResource LabelTemplate}"> </ContentPage>

How to change its Text content and its BackgroundColor (different user role has different color) in the behind code (MyTemplatedPage.xaml.cs)?

Thanks for your help

Tagged:

Posts

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    A content page which use this template can't find the label, lblUsername

    Nor should it be able to, or even trying to.

    You have to bind those properties to properties on the model or viewmodel

    Naming a UI control in a template is pointless. If you had 100 items of that type in a view you can't have 100 controls all with the same name. The fact that you are naming it at all hints that you are trying to affect your UI from code behind; which is wrong 99% of the time.

    I suspect the real issue here is an understanding of MVVM or separating UI from logic. It seems like you're trying to affect UI from your logic code, and that's the real problem.

  • seanydaseanyda GBMember ✭✭✭✭✭
    edited February 2017

    @ClintStLaurent is right, However if you want a nasty way of doing it then use MessagingCenter

    In your control template add this
    MessagingCenter.Subscribe<ViewCustomerTablet, string>(this, "ShowInfo", (pageDetails, textToUpdate) =>
    {
    // set label text here...
    string labelText = textToUpdate;
    });

    Replace ViewCustomerTablet with the ContentPage name.

    When you want to update the text do this
    MessagingCenter.Send<ViewCustomerTablet, string>(this, "ShowInfo", "TEXT TO UPDATE");

    Unfortunately not everyone follows the MVVM pattern like myself :P So have to come up with awkward workarounds haha

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Nasty

    ... Does not begin to describe that.

    Sure sometimes we all have to do work-a-rounds for parts that are broken or missing. But I'd highly recommend you stick with doing things right, rather than fast and nasty. The more you pile that stuff into your app the more you're painting yourself into a corner and the less anyone can or will help you out of jam of your own making.

  • seanydaseanyda GBMember ✭✭✭✭✭
    edited February 2017

    @ClintStLaurent said:

    Nasty

    ... Does not begin to describe that.

    Sure sometimes we all have to do work-a-rounds for parts that are broken or missing. But I'd highly recommend you stick with doing things right, rather than fast and nasty. The more you pile that stuff into your app the more you're painting yourself into a corner and the less anyone can or will help you out of jam of your own making.

    Yeah you're right. However I've found that ControlTemplates are really limited, It's literally just a template and it can't be modified without using the MessagingCenter. So in his case, If he hasn't built his app around the MVVM pattern and isn't planning on rewriting the app it might be the only solution. So It's still worth sharing imo.

    Also even if he was using MVVM I still don't think it would be possible modifying the Control Template without MessagingCenter.

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    @lpdavies

    I've found that ControlTemplates are really limited,

    That's why I don't bother with them. My outlook is to use something that works and is fairly robust instead of using something weak, then write band-aids all over that. There is always another way to do something. If the control template support sucks then don't use it. Make reusable ContentViews instead... or better Styles... or smarter ControlTemplates...

    Most of the people I see trying to use ControlTemplates are doing it where they should be using a template anyway. They just want to predefine a color, font, size and so on. The example the poster here showed is just another case of that. Just make a style for the label and bind the text as you would in proper MVVM.

    This is not a case of the template being limited or not doing its job. Its a case of the OP using a hammer when he should be using a screwdriver.

  • xamarin_newbiexamarin_newbie USMember ✭✭

    @ClintStLaurent and @lpdavies,

    Thank you very much for your help

    I'm a new Xamarin developer. Our app will have some pages and most pages have the same pattern: a top bar which will show user's personal info, and a bottom menu bar has the most useful page's menu items. The different contents can be added between the top bar and bottom bar in a page when the page implements this pattern. And the top bar and bottom bar's content or color can be changed when needed in this page. What's the bast way to design this pattern which can be used for those pages and can change the top bar's content and a menu item's color in the bottom bar easily?

    @ClintStLaurent said:
    @lpdavies

    I've found that ControlTemplates are really limited,

    That's why I don't bother with them. My outlook is to use something that works and is fairly robust instead of using something weak, then write band-aids all over that. There is always another way to do something. If the control template support sucks then don't use it. Make reusable ContentViews instead... or better Styles... or smarter ControlTemplates...

    Most of the people I see trying to use ControlTemplates are doing it where they should be using a template anyway. They just want to predefine a color, font, size and so on. The example the poster here showed is just another case of that. Just make a style for the label and bind the text as you would in proper MVVM.

    This is not a case of the template being limited or not doing its job. Its a case of the OP using a hammer when he should be using a screwdriver.

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    most pages have the same pattern: a top bar which will show user's personal info, and a bottom menu bar has the most useful page's menu items.

    That's actually the next article I'm writing for my blog. With any luck maybe it will be done over the weekend. I'm trying to write up articles in something of a step-by-step to making a good base app - while at the same time using questions here to drive priorities. I see lots of people asking about this, about customizing the title bar etc. So this is what I've been working towards over the last couple articles and into the next one or two.

    But here's the bullet points of what I'm going to write up. Maybe it can give you some ideas of where to go.
    • Plan A - Make a header and foot control and place that on each page. Properties on these controls will/can update based on the binding context of that page. IE The header can show a title based on the 'Title' property of the ViewModel backing that page. This is the fastest implementation since you can still use the built-in navigation, but you do have to include it in the XAML of each new page. Since it is a single control, just being used over and over your maintenance is still in one place. And you can have pages that DON'T use the header and footer for special cases.
    • Pan B - Don't use a bunch of pages: Just use 1, and make a ContentView for the middle body region and bind the Content of the ContentView. Then you make ContentViews for each page you want to show instead of ContentPage. This makes for very performant response, no page pushing animations to fight etc., but you'll need to roll your own Navigation system since you aren't pushing pages.

  • xamarin_newbiexamarin_newbie USMember ✭✭

    @lpdavies,
    Do you have any suggestion about my question:

    Our app will have some pages and most pages have the same pattern: a top bar which will show user's personal info, and a bottom menu bar has the most useful page's menu items. The different contents can be added between the top bar and bottom bar in a page when the page implements this pattern. And the top bar and bottom bar's content or color can be changed when needed in this page. What's the bast way to design this pattern which can be used for those pages and can change the top bar's content and a menu item's color in the bottom bar easily?

    @lpdavies said:

    @ClintStLaurent said:

    Nasty

    ... Does not begin to describe that.

    Sure sometimes we all have to do work-a-rounds for parts that are broken or missing. But I'd highly recommend you stick with doing things right, rather than fast and nasty. The more you pile that stuff into your app the more you're painting yourself into a corner and the less anyone can or will help you out of jam of your own making.

    Yeah you're right. However I've found that ControlTemplates are really limited, It's literally just a template and it can't be modified without using the MessagingCenter. So in his case, If he hasn't built his app around the MVVM pattern and isn't planning on rewriting the app it might be the only solution. So It's still worth sharing imo.

    Also even if he was using MVVM I still don't think it would be possible modifying the Control Template without MessagingCenter.

  • DavidDancyDavidDancy AUMember ✭✭✭✭

    @Charlie2017, @ClintStLaurent Funny you should be discussing this! I've been running an experiment along these lines and I just figured it out.

    The key is to have a ContentView as the ControlTemplate, and in the OnParentSet callback of the template set a handler for the parent's OnBindingContextChanged event. The parent will eventually be set to the ContentPage that's applying the template.

    When that gets triggered, set the template's BindingContext to the parent's BindingContext (or whatever other INotifyPropertyChanged object that suits you), and you're home and dry. Here's the relevant code-behind for the template:

    protected override void OnParentSet()
    {
        base.OnParentSet();
        Parent.BindingContextChanged += HandleParentBindingContextChanged;
    }
    
    private void HandleParentBindingContextChanged(object sender, EventArgs e)
    {
        if (Parent.BindingContext == null)
            return; 
        BindingContext = Parent.BindingContext;  // or some other INotifyPropertyChanged
    }
    
  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    @DavidDancy

    This is what I love about coding... The art and style mixed with science. Ask 10 developers how they would do something and you'll get 10 different ways - and they're probably all correct but different. That's where the individual's style can shine through.

    I took a different approach. A page with 3 controls: header, body, footer. The body is a ContentView whose content binded to a property on my ViewModel (CurrentPage). The BindingContext of the enclosing page is binded to the BindingContext of the CurrentPage ContentVIew. Thus the header is displaying properties relevant to the content in the body. The ViewModel for the body parts derives from a base view model so they all have properties for icon, title, color and so on. Everything updates automagically because of the binding: No code behind.

    <controls:PageHeaderControl Grid.Row="0" />
    
    <Grid 
          Grid.Row="1"
          VerticalOptions="FillAndExpand">
    
        <ScrollView>
            <ContentView x:Name="body"
                          VerticalOptions="FillAndExpand"
                          Content="{Binding CurrentPage,
                                            Mode=OneWay}" />
        </ScrollView>
    
    </Grid>
    
    <controls:PageFooterControl Grid.Row="2" />
    

    So where David sounds like he's pushing BindingContext down to the middle control, I'm pushing it from the middle control. Just goes to show you there is no single right way to skin a cat.

  • xamarin_newbiexamarin_newbie USMember ✭✭

    @ClintStLaurent,

    It is a interesting way to switch the body part and just only use a single page with the top bar and bottom bar. Unlike desktop app, the performance especially on Android isn't good when navigate from one page to another and the xamarin form template control has some limitations. My questions are

    1. When need to change the body view from the current to a new view, the current view can be removed or deleted? And the new view can be dynamically added into?

    2. If a body view, for example, the home "page" view which allows users to switch to other body view. In the home view, which can create a new body view and add the new body view into the page?

    I'd like to study your blog for this solution. It is better with a simple example. When will it be posted?

    That's actually the next article I'm writing for my blog. With any luck maybe it will be done over the weekend. I'm trying to write up articles in something of a step-by-step to making a good base app - while at the same time using questions here to drive priorities. I see lots of people asking about this, about customizing the title bar etc. So this is what I've been working towards over the last couple articles and into the next one or two.

    But here's the bullet points of what I'm going to write up. Maybe it can give you some ideas of where to go.
    • Plan A - Make a header and foot control and place that on each page. Properties on these controls will/can update based on the binding context of that page. IE The header can show a title based on the 'Title' property of the ViewModel backing that page. This is the fastest implementation since you can still use the built-in navigation, but you do have to include it in the XAML of each new page. Since it is a single control, just being used over and over your maintenance is still in one place. And you can have pages that DON'T use the header and footer for special cases.
    • Pan B - Don't use a bunch of pages: Just use 1, and make a ContentView for the middle body region and bind the Content of the ContentView. Then you make ContentViews for each page you want to show instead of ContentPage. This makes for very performant response, no page pushing animations to fight etc., but you'll need to roll your own Navigation system since you aren't pushing pages.

Sign In or Register to comment.