Best way to define a parent page to allow embedding of XAML.

What's the best way to display content in a page with a standard layout throughout the application?

I have an app that has a fixed format page layout with a header containing buttons a footer and a bit in the middle that I want to swap out as I navigate around.

<ContentPage>  
  <ContentPage.Content>  
    <StackLayout Orientation="Vertical">
      <Label Text="{Binding Item1}"/>
      <Button Text="Options" Command="{Binding ACommand}"/>
      <!-- my content here...-->
    </StackLayout >
  </ContentPage.Content>  
</ContentPage>

My options are:
1. Use a ContentTemplate
2. Use views.
3. Cut and paste outer into each new page.
Which is best?

Detail below....

1. Use a ContentTemplate

My xaml would then look like...

<Application.Resources>
    <ResourceDictionary>
        <!--template theme 1-->
        <ControlTemplate x:Key="MyTemplate1">
            <StackLayout Orientation="Vertical">
                <Label Text="{Binding Item1}"/>
                <Button Text="Options" Command="{Binding ACommand}"/>
                <ContentPresenter />
            </StackLayout >
        </ntrolTemplate>
    </ResourceDictionary>
</Application.Resources>

and my page....

<ContentPage>
    <ContentView x:Name="contentView"
               ControlTemplate="{StaticResource MyTemplate1}">
        <ContentView.Padding>
            <OnPlatform x:TypeArguments="Thickness" iOS="0,20,0,0" />
        </ContentView.Padding>
        <!-- My content here-->
        <Grid>
            <Label Text = My clever page content" />
            <!-- I can put anything in here..... -->
        </Grid>
    </ContentView>
</ContentPage>

The advantage here is all my pages are logically seperate.

2. Use views.

I define a view for each of my different pages

<ContentView x:Class="MyApp.ContainerView">
    <Grid>
        <Label Text = My clever page content" />
        <!-- I can put anything in here..... -->
    </Grid>
</ContentView>

and....

<ContentView x:Class="MyApp.AnotherReallyCleverContentView">
    <StackLayout Orientation="Vertical">
        <Label Text="Page1's content."/>
    </StackLayout >
</ContentView>

and then pages are ...

<ContentPage>
    <ContentPage.Content>
        <StackLayout Orientation="Vertical">
            <Label Text="{Binding Item1}"/>
            <Button Text="Options" Command="{Binding ACommand}"/>
            <views:ContainerView />
        </StackLayout >
    </ContentPage.Content>
</ContentPage>

and I can then swap the views out programatically, doing something like....

 ContainerPage = new MainPage();

 ContainerPage.FindByName<ContentView>("Container").Content = (ContentView)Activator.CreateInstance(AnotherReallyCleverContentView)

Posts

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Ask a dozen developers, you'll get a dozen 'best' ways.

    ControlTemplate is pretty standard, easy for junior developers to follow, and every page is still a page so you don't have to re-invent navigation. Of course that is a double-edge sword. It does mean that every page is still its own page. When you navigate you'll see your header/footer move with the page... if it has lots of images they have to re-load... etc.

    I'm partial to really having one page, with a ContentView between the header and footer. Then I move other views in and out of that placeholder. It means my navigation manager handles navigation which would happen regardless so I can control things as I see fit based on the user's permissions, requirements before loading a given page etc. You can databind that middle area pretty easily: <ContentView.Source = {Binding AppscopeVM.CurrentView> for example, and do all your navigation at an app-scoped level blah blah blah

    It also means the header and footer are binded to a given context, while the content in the body of the page has its own context. Which is clean to my way of doing things.

  • jembirjembir Member ✭✭

    Thanks Clint - I looked at the Control Template - but it has limitations in thet Visual Studio won't display pages that use the template.
    So, even as I type, I'm going exploring down the View Route.

    How does that fit into (simple) MVVMis something for a bit later....

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Visual Studio won't display pages that use the template.

    Umm.... I've done it many times. Not sure what issue you're running into.

    'm going exploring down the View Route.
    How does that fit into (simple) MVVM

    No problem. As I said:

    You can databind that middle area pretty easily: <ContentView.Source = {Binding AppscopeVM.CurrentView> for example, and do all your navigation at an app-scoped level blah blah blah

  • jembirjembir Member ✭✭

    For the benefit of the hard pof thinking (me) can you expand on:

    <ContentView.Source = {Binding AppscopeVM.CurrentView> for example, and do all your navigation at an app-scoped level blah blah blah

    a bit?

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Since you aren't navigating ContentPages like the normal/simple/sample apps - you'll have to make your own navigation class.

    In the technique I mentioned you're changing ContentViews instead of pages. So you'll need to have your own queue of those views. When the user wants to go back your navigation stack will then have to pop the current view off the queue and provide the previous one. And so on.

  • jembirjembir Member ✭✭

    On another note - relating to content templates.
    If you download the sample content template build it and then look at the HomePage.xaml - it shows the control templates only, and not the additional content on the page.

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Ok. And? Why do I want to do that?

  • jembirjembir Member ✭✭

    You probably don't :) I was pointing out that Visual Studio doesn't display the additional contents of a page that uses a ContentTemplate. It simply shows the Control Template content. Which makes the Previewer for any pages that use a Control Templates pretty pointless and, arguably, Control Templates a bit less useful.

    Umm.... I've done it many times. Not sure what issue you're running into.

    It doesn't work on samples produced on Xamarin's site - so I was wondering if you were doing something magical?

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Control Templates a bit less useful.

    ControlTemplates work fine.

    Which makes the Previewer for any pages that use a Control Templates pretty pointless

    The Previewer is pointless in general. There are countless threads here for that. Its basically worthless on anything that even begins to approach a grown-up app. Its fine for really basic tutorial type apps. But nothing real-world

    so I was wondering if you were doing something magical?

    Nope. Right off the Xamarin page for ControlTemplates
    https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/templates/control-templates/creating/

    ControlTemplate in App.xaml

                <!--#region Control Templates-->
                <ControlTemplate x:Key="PageTemplate">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="50" />
                            <RowDefinition Height="*" />
                            <RowDefinition Height="50" />
                        </Grid.RowDefinitions>
                        <Grid BackgroundColor="Blue"
                              Row="0">
                            <Label Text="Header" />
                        </Grid>
                        <ContentPresenter Grid.Row="1" />
                        <Grid BackgroundColor="Red"
                              Row="2">
                            <Label Text="Footer" />
                        </Grid>
                    </Grid>
                </ControlTemplate>
                <!--#endregion Control Templates-->
    

    CameraPg specifying the control template to use

    Screenshot of the running app, on the camera page

  • jembirjembir Member ✭✭

    Many thanks for this. I think I was placing waaaaayyyyy too much faith in the previewer.

    My app doesn't really fit in the to the built-in navigation - and I like the idea of switching views in and out (it def looks slicker). Do you have any references for a view navigator?

    Finding this forum really useful btw - now a convert...

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    Do you have any references for a view navigator?

    Nothing I can give out. I built it for our company app so it would violate my NDA to give out specifics.

    But the concept is pretty much as I described. On the Page you bind the view to a SelectedView property on your ViewModel. You keep a collection/List/queue.... some sort of collection of your liking for the views you've shown. When your user moves forward, you add to the queue and make the new item the SelectedView. When the user goes back, you pop off the latest and make the new .Last() item the new SelectedView.

    Everything after that like user permissions to see a page etc. is just icing you keep adding here and there.

  • jembirjembir Member ✭✭

    So...if I do...

    <StackLayout>            
            <ContentView Content= "{Binding TestNavVM.CurrentView}"/>
    </StackLayout>
    

    and then in VM code....

    public View CurrentView
    {
        get{return view;}
        set{view = value;OnPropertyChanged();}
    }
    

    If I then set CurrentView = new myView();

    it returns the view! Hooray! But it isn't displayed.

Sign In or Register to comment.