I am new to .NET MAUI and making a page "MainPage
" with flyoutPage.
In the page, I have values bounded from MainPageViewModel
and Flyout
.
When I try to set BindingContext
in MainPage.xaml.cs
, I get Flyout and Detail must be set before adding FlyoutPage to a container
error.
But if I add InitializeComponent()
to the first constructor with no parameter, it stops complaining about it.
Is keeping both of InitializeComponent()
the right way to fix this? Or am I missing something else?
In MainPage.xaml,
<?xml version="1.0" encoding="utf-8" ?>
<FlyoutPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:Realizer.ViewModels"
xmlns:models="clr-namespace:Realizer.Models"
xmlns:local="clr-namespace:Realizer.Pages"
x:Class="Realizer.Pages.MainPage"
x:DataType="vm:MainPageViewModel"
Title="Home">
<FlyoutPage.Flyout>
<ContentPage Title="Home page" BackgroundColor="LightGrey">
<VerticalStackLayout>
<CollectionView>
<CollectionView.ItemsSource>
<x:Array Type="{x:Type models:Flyout}">
<models:Flyout Title="Home"
IconSource="home.png"
Command="GoToHomePageCommand"/>
<models:Flyout Title="Clients"
IconSource="person.png"
Command="GoToClientsPageCommand"/>
</x:Array>
</CollectionView.ItemsSource>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="20, 5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="{Binding IconSource, Source={RelativeSource AncestorType={x:Type models:Flyout}}}"
Scale="1.5"/>
<Button Grid.Column="1"
Margin="5"
Text="{Binding Title, Source={RelativeSource AncestorType={x:Type models:Flyout}}}"
Command="{Binding Command, Source={RelativeSource AncestorType={x:Type models:Flyout}}}"
FontSize="16"
FontAttributes="Bold"
TextColor="Black"
HeightRequest="60"
Padding="0,0,110,0"
BackgroundColor="LightGray"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Label Text="this is it"
Margin="20"/>
</VerticalStackLayout>
</ContentPage>
</FlyoutPage.Flyout>
<FlyoutPage.Detail>
<NavigationPage BarBackgroundColor="Navy"
BarTextColor="Black"
Title="Home">
<x:Arguments>
<ContentPage Title="Home" BackgroundColor="White">
<VerticalStackLayout>
<Label Text="this is detail"
Margin="20"/>
</VerticalStackLayout>
</ContentPage>
</x:Arguments>
</NavigationPage>
</FlyoutPage.Detail>
</FlyoutPage>
In MainPage.xaml.cs
using Realizer.ViewModels;
namespace Realizer.Pages;
public partial class MainPage : FlyoutPage
{
public MainPage(){
//InitializeComponent();
}
public MainPage(MainPageViewModel viewModel)
{
InitializeComponent();
BindingContext = viewModel;
}
}
In MainPageViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Realizer.Pages;
namespace Realizer.ViewModels
{
public partial class MainPageViewModel : ObservableObject
{
public MainPageViewModel()
{
}
[RelayCommand]
private async Task GoToClientsPage()
{
await Application.Current.MainPage.Navigation.PushAsync(new ClientsPage());
}
}
}
In App.xaml.cs
using Realizer.Pages;
namespace Realizer
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MainPage();
}
}
}
When you call code MainPage = new MainPage();
to MainPage
, it will call the default constructor(no parameter) of MainPage
to initialize data for this page.
From document Get started with XAML,we could find that :
The MainPage constructor calls
InitializeComponent
, which initializes all the objects defined in the XAML file, connects them all together in parent-child relationships, attaches event handlers defined in code to events set in the XAML file, and sets the resultant tree of objects as the content of the page.
So, we should call method InitializeComponent()
to initialize all the objects defined in the XAML file after navigating to this page by code MainPage = new MainPage();
. Otherwise, the code will report the error you mentioned.