Databinding in XAML for MasterDetailPage in Xamarin.Forms - xaml

So far, most examples using Xamarin.Forms are using C# for building up the UI. I prefer using XAML for the UI, and databind it to ViewModels.
I'm having trouble using the Xamarin.Forms.MasterDetailPage in combination with XAML, and I can't seem to port the C# example to XAML + ViewModels.
This is the XAML I got so far:
<?xml version="1.0" encoding="UTF-8" ?>
<MasterDetailPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:NSContacten;assembly=NSContacten"
x:Class="MasterDetailExample.Main"
Title="Master Detail Example">
<MasterDetailPage.Master BindingContext="{Binding Menu}">
<ContentPage Padding="5, 25">
<StackLayout Orientation="Vertical">
<Label Text="Master" HorizontalOptions="Center" />
<Label Text="{Binding Subtitle}" HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail BindingContext="{Binding Detailpage}">
<ContentPage Padding="5, 25">
<StackLayout Orientation="Vertical">
<Label Text="Detail" HorizontalOptions="Center" />
<Label Text="{Binding Subtitle}" HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
The component works: I do see the 'Master' and 'Detail' labels. The bound labels (on the BindingContext objects) are not displayed.
I've used loads of different combinations, but I'm still stuck: How does this work? Is my binding incorrect (should it be on the "ContentPage"), can't I bind to the .Master and .Detail properties etc.? How should the "Menu" and "Detailpage" bindings look like?
It would be a huge help if anyone could help me out! The next step would be that the .Detail will be changed when a button is pressed in the .Master . Thanks in advance!

Your Xaml is almost ok, but:
The {BindingContext} are invalid on the properties and should be on the ContentPage elements
MasterDetailPage.Master require a Page.Title to be set, or it throws.
Here's the correct Xaml working for me:
<?xml version="1.0" encoding="UTF-8" ?>
<MasterDetailPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:NSContacten;assembly=NSContacten"
x:Class="MasterDetailExample.Main"
Title="Master Detail Example">
<MasterDetailPage.Master>
<ContentPage Padding="5, 25" BindingContext="{Binding Menu}" Title="Master">
<StackLayout Orientation="Vertical">
<Label Text="Master" HorizontalOptions="Center" />
<Label Text="{Binding Subtitle}" HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<ContentPage Padding="5, 25" BindingContext="{Binding Detailpage}">
<StackLayout Orientation="Vertical">
<Label Text="Detail" HorizontalOptions="Center" />
<Label Text="{Binding Subtitle}" HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
I tested it with an anonymous type as the page view model:
public MyMDPage ()
{
InitializeComponent ();
BindingContext = new {
Menu = new { Subtitle = "I'm Master" },
Detailpage = new { Subtitle = "I'm Detail" }
};
}
and this works just fine. In your case, you probably want concrete types instead of anonymous ones for your view model, but you get the idea.

Related

reusable contentview .NET MAUI

Simply, I have a contentview such as;
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="myapp.customstacklayout">
<StackLayout>
<StackLayout>
<StackLayout x:Name="header">
<!-- some title things here, such as a header label etc-->
</StackLayout>
<StackLayout x:Name="content">
<!--Contents should be added here when reused-->
</StackLayout>
<StackLayout x:Name="footer">
<!-- some footer things here, such as a summary label etc-->
</StackLayout>
</StackLayout>
<!--Not here-->
</StackLayout>
</ContentView>
and i want to reuse it in a ContentPage such as;
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mycontrols="clr-namespace:myapp"
x:Class="myapp.mainpage">
<StackLayout>
<mycontrols:customstacklayout>
<Button Text="TestButton"/>
<Entry Text="TestEntry"/>
<Label Text="TestLabel"/>
.... and etc..
</mycontrols:customstacklayout>
</StackLayout>
</ContentPage>
to create such a reusable item, i think, in xaml, there has to be something for contentview to point which IView item the children should be added in
Any idea or a piece of code for that?
Thanks in advance.
Ender
EDIT: i changed my contentview xaml for using ControlTemplate. Added Resources and a contentPresenter at the point where i want to show the children added. But still can not see the children
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="myapp.customstacklayout">
<ContentView.Resources x:Key="template">
<ControlTemplate>
<StackLayout>
<StackLayout>
<StackLayout x:Name="header">
<!-- some title things here, such as a header label etc-->
</StackLayout>
<StackLayout x:Name="content">
<!--Contents should be added here when reused-->
<ContentPresenter/>
</StackLayout>
<StackLayout x:Name="footer">
<!-- some footer things here, such as a summary label etc-->
</StackLayout>
</StackLayout>
<!--Not here-->
</StackLayout>
</ControlTemplate>
</ContentView.Resources>
</ContentView>
Well, if you want to create a reusable ContentView .NET MAUI, you can create Control Templates with Content Presenter and then reuse it in the page you want.
You can refer to below detailed steps on how to use it.
1. Create a custom control: CustomControl.xaml that inherits from ContentView with a custom BindableProperty like below:
XAML:
<ContentView.ControlTemplate>
<ControlTemplate>
<Frame>
<VerticalStackLayout>
<Label Text="{TemplateBinding Title}"/>
<ContentPresenter/>
</VerticalStackLayout>
</Frame>
</ControlTemplate>
</ContentView.ControlTemplate>
Code-behind:
public partial class CustomControl : ContentView
{
public static readonly BindableProperty TitleProperty =
BindableProperty.Create(nameof(Title), typeof(string), typeof(CustomControl) );
public CustomControl()
{
InitializeComponent();
}
public string Title
{
get => GetValue(TitleProperty) as string;
set => SetValue(TitleProperty, value);
}
}
2. You can reuse it multiples in the MainPage.xaml like below:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:MauiAppCustomDemo.Controls"
x:Class="MauiAppCustomDemo.MainPage">
<ScrollView>
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
<controls:CustomControl Title="Hello World">
<VerticalStackLayout>
<Label Text="Label 1"/>
<Label Text="Label 2"/>
</VerticalStackLayout>
</controls:CustomControl>
<controls:CustomControl Title="Hello again">
<HorizontalStackLayout>
<Label Text="Label 3"/>
<Label Text="Label 4"/>
</HorizontalStackLayout>
</controls:CustomControl>
</VerticalStackLayout>
</ScrollView>
</ContentPage>
Microsoft Official reference link:https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/controltemplate?view=net-maui-7.0

XAML Page With Grid And Button

I have a grid which will take up most of my Xamarin.Forms Page, and I want to add a button below the grid. My issue is that I am using the below syntax to add the button, however the button fills the entire page.
What do I need to change so that the button appears directly below the grid?
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XF.Pages.AEI" >
<ContentView Content="{Binding ApprovedUserGrid,Mode=TwoWay}" Padding="0,30,0,0"/>
<Button Command="{Binding OkayCommand}" Text="Okay" TextColor="White"
FontAttributes="Bold" FontSize="Large" HorizontalOptions="FillAndExpand"
BackgroundColor="#088da5" />
</ContentPage>
This is C# for my grid (not where I actually bind, but the creation)
private Grid _Grid;
public Grid TestGrid
{
get { return _Grid ?? (_Grid=new Grid()); }
set
{
_Grid = value;
NotifyPropertyChanged();
}
}
EDIT
I edit code to read like this, and there are no errors, but I do not see my button on the page?
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XF_Login.Pages.ApproveUsers" >
<StackLayout Orientation="Vertical" Padding="30" Spacing="40">
<ContentView Content="{Binding ApprovedUserGrid,Mode=TwoWay}" Padding="0,30,0,0"/>
<Button Command="{Binding OkayCommand}" Text="Okay" TextColor="White"
FontAttributes="Bold" FontSize="Large" HorizontalOptions="FillAndExpand"
BackgroundColor="#088da5" />
</StackLayout>
</ContentPage>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XF_Login.Pages.ApproveUsers" >
<StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand" Padding="30" Spacing="40">
<ContentView VerticalOptions="FillAndExpand" Content="{Binding ApprovedUserGrid,Mode=TwoWay}" Padding="0,30,0,0"/>
<Button Command="{Binding OkayCommand}" Text="Okay" TextColor="White"
FontAttributes="Bold" FontSize="Large" HorizontalOptions="Center"
BackgroundColor="#088da5" />
</StackLayout>
</ContentPage>

Xamarin MasterDetailPage ContentPropertyAttribute

I'm trying to learn Xamarin and I was doing a simple MasterDetailPage to run on iOS. After running the code I got this error:
Can not set the content of MasterDetailPage as it doesn't have a ContentPropertyAttribute
Below is my XAML file code snippet:
<?xml version="1.0" encoding="utf-8"?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MasterDetailLearing" x:Class="MasterDetailLearing.MainPage">
<!-- Place new controls here -->
<Label Text="Welcome to Xamarin.Forms!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
<MasterDetailPage.Master>
<ContentPage Padding="10" BackgroundColor="Gray" Title="Master">
<ContentPage.Content>
<StackLayout Margin="5,30,5,5">
<Label Text="Master Page"></Label>
</StackLayout>
</ContentPage.Content>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<ContentPage Padding="10">
<ContentPage.Content>
<StackLayout Margin="5,30,5,5">
<Label Text="Detail Page"></Label>
</StackLayout>
</ContentPage.Content>
</ContentPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
a MasterDetail page only has Master and Detail children. You cannot include any other content as a direct child. So your Label needs to be in either the Master or the Detail, it cannot be a direct child of the page.

How to create Footer which can be used for all the xamarin Form pages?

I am creating an app in which i want the footer which will be common for all xaml pages.I tried solution given on this link xamarin forum
but it is showing error for partial class bcoz I'm using xamarin xaml form page while inheriting the class PageToInherit.If I just use page (only .cs file) then there is no error.
public partial class TodoList : PageToInherit
{
public TodoList()
{
InitializeComponent();
this.Title = "TodoList page";
Button button = new Button();
button.Text = "BUTTON 1";
MainStackLayout.Children.Add(button);
Content = MainStackLayout;
}
}
I think you can take a look to TemplatedPage
Create a ControlTemplate
<?xml version="1.0" encoding="utf-8" ?>
<Application
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Mobile.App">
<Application.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="MainPageTemplate">
<StackLayout>
<Label Text="Header Content" FontSize="24" />
<ContentPresenter />
</StackLayout>
</ControlTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
Apply the ControlTemplate
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Mobile.MainPage"
ControlTemplate="{StaticResource MainPageTemplate}">
<Label Text="Main Page Content" FontSize="18" />
</ContentPage>
Use TemplateBinding
<ControlTemplate x:Key="MainPageTemplate">
<StackLayout>
<Label Text="{TemplateBinding BindingContext.HeadingText}" FontSize="24" />
<ContentPresenter />
</StackLayout>
</ControlTemplate>
Here the Blog
For those who are still looking for this.
Use ContentView for creating reusable xaml views.
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="xxx.FooterView">
<ContentView.Content>
<RelativeLayout VerticalOptions="End" HorizontalOptions="Fill" HeightRequest="42" RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}">
<Label HeightRequest="42" VerticalTextAlignment="Center" Text="Copyright © 2017. All rights reserved." HorizontalTextAlignment="Center" RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}" />
</RelativeLayout>
</ContentView.Content>
</ContentView>
and use it in your page like any control
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="xxx.Page1" xmlns:local="clr-namespace:xxx;assembly=xxx" >
<local:FooterView VerticalOptions="End" HeightRequest="45"/>
//other views and layouts
</ContentPage>
Hope it helps.

Implement Reusable elements in xamarin forms

Iam trying to define reusable components in my xamarin app. My intention is to use same xaml in multiple files. For example, I need to define common header for my app. I tried to implement this in following way : Define required xaml in separate file. Use the class name associated for reusing in any other xaml.
Reusable xaml :
<?xml version="1.0" encoding="utf-8" ?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="AppHeader" BackgroundColor="White"
Spacing="1"
VerticalOptions="Start">
<StackLayout Padding="0,10,0,10"
BackgroundColor="Blue"
Orientation="Horizontal"
Spacing="0">
<Label
Text="AppName"
HorizontalTextAlignment="Center"
HorizontalOptions="Center"
TextColor="White"
></Label>
</StackLayout>
</StackLayout>
Associated Class :
public partial class AppHeader : StackLayout
{
public AppHeader ()
{
InitializeComponent();
}
}
Usage in xaml
<?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:common="clr-namespace:MyApp;assembly=MyApp"
x:Class="MyApp.SampleView">
<StackLayout>
<common:AppHeader></common:AppHeader>
</StackLayout>
</ContentPage>
While running the app, Im getting following error for reusable xaml file:
"The name 'InitializeComponent' does not exist in the current context"
The implementation look simple, but Im not able to identify what is missing.
Any solution for this?
Any help would be much appreciated.
Thanks
In your StackLayout you have an attribute for your class: x:Class="AppHeader". This should specify the fully qualified class name including the namespace. So edit it to be something like:
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="YouNameSpace.AppHeader" BackgroundColor="White"
Spacing="1"
VerticalOptions="Start">
<StackLayout Padding="0,10,0,10" ...
Remove InitializeComponent(); from your AppHeader constructor. InitializeComponent() is only used by ContentPages.
Also, just noticed the XML you have in your AppHeader XAML. Change that XAML to this (removing all the boilerplate XAML that is only needed in a ContentPage:
<StackLayout BackgroundColor="White"
Spacing="1"
VerticalOptions="Start">
<StackLayout Padding="0,10,0,10"
BackgroundColor="Blue"
Orientation="Horizontal"
Spacing="0">
<Label Text="AppName"
HorizontalTextAlignment="Center"
HorizontalOptions="Center"
TextColor="White"></Label>
</StackLayout>
</StackLayout>