Nested View not showing Xamarin Forms - c#

I want to be able to display LessonView.xaml within MainPage.xaml.
Here is my attempt below.
Am i missing something important that it wont display ?
MainPage.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:local="clr-namespace:KanjiStudy"
x:Class="KanjiStudy.MainPage"
xmlns:views="KanjiStudy.View.LessonView">
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<Label Text="Welcome to Xamarin.Forms!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<views:View.LessonView>
</views:View.LessonView>
<StackLayout Margin="0,0,0,20" Padding="20,0,20,0" VerticalOptions="End" HorizontalOptions="Center" Orientation="Horizontal">
<Button Margin="20,0,50,20" FontSize="Large" HorizontalOptions="Start" Text="Study" >
</Button>
<Button Margin="50,0,20,20" FontSize="Large" Text="Test" Clicked="Button_Clicked">
</Button>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
LessonView.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="KanjiStudy.View.LessonView">
<ContentView.Content>
<StackLayout>
<Label Text="i am a view" />
</StackLayout>
</ContentView.Content>
</ContentView>

The namespace declaration in MainPage.xaml should only include the namespace of where the view view:
xmlns:views="KanjiStudy.View">
Then when displaying the view, use the xmlns name and C# class name (but not the C# namespace name), as such:
<views:LessonView>
</views:LessonView>
The way to think about it is that the XAML parser will create an instance of the class for the view by taking the namespace path from the xmlns declaration, and finding the classname in there.
In other words, in the original code, it will attempt to look in the namespace KanjiStudy.View.LessonView. Since the full namespace + class name for your view is KanjiStudy.View.LessonView, put the namespace parts in the xmlns, and the classname on the XML tag where you want the view.

I was able to find a wpf tutorial this did something similar here http://blog.scottlogic.com/2012/02/06/a-simple-pattern-for-creating-re-useable-usercontrols-in-wpf-silverlight.html
MainPage.xaml
This needed to use the following namespace
xmlns:local="clr-namespace:KanjiStudy.View">
instead of
xmlns:views="KanjiStudy.View.LessonView">
Then in the body i can pull in multiple lessonView objects so
<?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="KanjiStudy.MainPage"
xmlns:local="clr-namespace:KanjiStudy.View">
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<StackLayout Orientation="Vertical" VerticalOptions="StartAndExpand">
<Label Margin="0,20,0,0" Text="Grade 1"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<StackLayout HorizontalOptions="CenterAndExpand" Orientation="Horizontal">
<local:LessonView Margin="10,10,10,10">
</local:LessonView>
<local:LessonView Margin="10,10,10,10">
</local:LessonView>
<local:LessonView Margin="10,10,10,10">
</local:LessonView>
</StackLayout>
</StackLayout>
<StackLayout Margin="0,0,0,20" Padding="20,0,20,0" VerticalOptions="End" HorizontalOptions="Center" Orientation="Horizontal">
<Button Margin="20,0,50,20" FontSize="Large" HorizontalOptions="Start" Text="Study" >
</Button>
<Button Margin="50,0,20,20" FontSize="Large" Text="Test" Clicked="Button_Clicked">
</Button>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>

Related

Pass a Binding into Reusable UI Element in MAUI

I'm trying to create a reusable ContentView that can be bound to an instance specific value. The view is defined as follows:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:element="clr-namespace:SimultaneousEquations.Elements"
x:Class="SimultaneousEquations.Elements.EquationElement">
<ContentView.BindingContext>
<element:EquationElement />
</ContentView.BindingContext>
<HorizontalStackLayout HorizontalOptions="Center">
<Label FontSize="22" Text="{Binding EquationAsString}" HorizontalOptions="Center" />
<Label>
<Label.Margin>8,0,0,0</Label.Margin>
</Label>
<Frame
WidthRequest="30"
HeightRequest="30"
CornerRadius="15"
BorderColor="Black"
Padding="0" >
<Label
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
Text="1"
TextColor="Black"
FontSize="22" >
</Label>
</Frame>
</HorizontalStackLayout>
</ContentView>
Code Behind:
namespace SimultaneousEquations.Elements;
public partial class EquationElement : ContentView
{
public EquationElement()
{
InitializeComponent();
}
public string EquationAsString
{
get => (string)GetValue(EquationAsStringProperty);
set => SetValue(EquationAsStringProperty, value);
}
public static readonly BindableProperty EquationAsStringProperty =
BindableProperty.Create(
nameof(EquationAsString),
typeof(string),
typeof(EquationElement),
"Equation Not Set"//string.Empty
);
}
I'm then trying to use it in a ContentPage. Using the Reusable elements causes the app to crash. Using similar code directly in the view works fine:
<?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:viewModels="clr-namespace:SimultaneousEquations.ViewModels"
xmlns:elements="clr-namespace:SimultaneousEquations.Elements"
x:Class="SimultaneousEquations.Views.SolveView"
Title="Solver">
<ContentPage.BindingContext>
<viewModels:SolveViewModel />
</ContentPage.BindingContext>
<VerticalStackLayout>
<!-- THIS CAUSES APP TO CRASH AT LAUNCH -->
<elements:EquationElement EquationAsString="{Binding FirstEquation.AsString}"/>
<!-- THIS WORKS -->
<HorizontalStackLayout HorizontalOptions="Center">
<Label FontSize="22" Text="{Binding FirstEquation.AsString}" HorizontalOptions="Center" />
<Label><Label.Margin>8,0,0,0</Label.Margin></Label>
<Frame
WidthRequest="30"
HeightRequest="30"
CornerRadius="15"
BorderColor="Black"
Padding="0" >
<Label
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
Text="1"
TextColor="Black"
FontSize="22" >
</Label>
</Frame>
</HorizontalStackLayout>
<Button HorizontalOptions="Center" Text="Solve" Command="{Binding SolveCommand}" />
</VerticalStackLayout>
</ContentPage>
Please can somebody help me get this to work. Thanks
EDIT: On android, the app just crashes without exception. I tried re-running the code that crashed in a WindowsMachine and got an exception in an auto-generated code file called Elements_EquationElement.xaml.sg.cs. The exception hit here:
private void InitializeComponent()
{
global::Microsoft.Maui.Controls.Xaml.Extensions.LoadFromXaml(this, typeof(EquationElement));
}
The message said Exception Unhandled - System.StackOverflowException: 'Exception_WasThrown'
I'm not sure that this appears very helpful.
The change I needed to make this work was to change the way I set up the Binding in the reusable ContentView, with a Binding Source and Path, like this:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:element="clr-namespace:SimultaneousEquations.Elements"
x:Class="SimultaneousEquations.Elements.EquationElement"
x:Name="ControlView">
<HorizontalStackLayout HorizontalOptions="Center">
<Label FontSize="22"
Text="{Binding Source={x:Reference ControlView}, Path=EquationAsString}"
HorizontalOptions="Center" />
<Label>
<Label.Margin>8,0,0,0</Label.Margin>
</Label>
<Frame
WidthRequest="30"
HeightRequest="30"
CornerRadius="15"
BorderColor="Black"
Padding="0" >
<Label
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
Text="{Binding Source={x:Reference ControlView}, Path=EquationNumber}"
TextColor="Black"
FontSize="22" >
</Label>
</Frame>
</HorizontalStackLayout>
</ContentView>
This example really helped me: .net Maui binding values multiple levels deep

Header ache - gap appears

When starting the app I get the UI as I want it. When returning to the same page I get the gap at the top. How can I fix this?
All navigation uses the Application.Current.MainPage = new SomePage(); shape.
The XAML is trivial:
<?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="ShipShapeMobile.LandingPage"
BackgroundImage="Gradient640x1136.png"
>
<ContentPage.Content >
<Grid
x:Name="grid"
>
<StackLayout
HorizontalOptions="Center"
VerticalOptions="Center"
>
<Image
HorizontalOptions="Center"
Source="ShipShapeShipA448x591.png"
VerticalOptions="Center"
Margin="50,15,50,15"
/>
<Image
HorizontalOptions="Center"
Source="TextOnlySS.png"
VerticalOptions="CenterAndExpand"
/>
<Image Source="hr7.png" Margin="20,10,20,10" />
<Button
x:Name="btnSignIn"
BackgroundColor="DodgerBlue"
BorderColor="White"
BorderWidth="1"
Clicked="BtnSignIn_OnClicked"
CornerRadius="15"
Image="Icon29.png"
Margin="50,10,50,10"
Text="SIGN UP"
TextColor="White"
/>
</StackLayout>
</Grid>
</ContentPage.Content>
It looks like in your LandingPage NavigationBar being displayed. Hide it in your xaml class itself.
NavigationPage.HasNavigationBar="false"
Use this in your top tag of ContentPage.

Getting the selected item from ItemTemplate in seperate file MVVM Xamarin.Forms

I have the PageView which is defined like this
<?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"
xmlns:view="clr-namespace:Fuse.ViewTemplates;assembly=Fuse"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="Fuse.Views.JoinPage">
<StackLayout Orientation="Vertical">
<Label Text="Games near your area .. "
VerticalOptions="Start"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
BackgroundColor="Transparent"
HorizontalOptions="CenterAndExpand" />
<ListView x:Name="listView" SelectedItem="{Binding SelcetedItem,Mode=TwoWay}"
RowHeight="150"
ItemsSource="{Binding CardList}" HasUnevenRows="True" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<view:CardViewTemplate/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
and the CardTemplateView defined like this
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Fuse.ViewTemplates.CardViewTemplate"
xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
xmlns:local="clr-namespace:Fuse"
xmlns:viewmodel="clr-namespace:Fuse.ViewModels"
x:Name="CardView"
>
<Frame IsClippedToBounds="True"
HasShadow="True"
BackgroundColor="White" >
<Frame.OutlineColor>
<OnPlatform x:TypeArguments="Color"
Android="Gray"
iOS="Gray"/>
</Frame.OutlineColor>
<Frame.Margin>
<OnPlatform x:TypeArguments="Thickness"
Android="7" iOS="7"/>
</Frame.Margin>
<Frame.Padding>
<OnPlatform x:TypeArguments="Thickness"
Android="10" iOS="5"/>
</Frame.Padding>
<StackLayout Orientation="Horizontal">
<Grid Grid.Row="3">
<Button Text="Join"
BackgroundColor="LawnGreen" BorderRadius="10" BorderWidth="10" HorizontalOptions="EndAndExpand">
</Button>
</Grid>
</StackLayout>
</Frame>
</ContentView>
What i want to do is bind the Button to a Command in viewmodel and pass the commandParameter to get the Item in the ListView corresponding to the Grid (aka Button) . This is a custom List Template which the ListView uses , it has a Button inside of it which when clicked should return the SelectedItem in the parent .
I hope I was clear .
Any Ideas ?
The shortest way would be to paste the ContentView into your ContentPage. Then your page needs a name and you can bind:
<Button Text="Join" Command="{Binding ElementName=PageName, Path=ViewModel.Command}" CommandParameter="{Binding}"
BackgroundColor="LawnGreen" BorderRadius="10" BorderWidth="10" HorizontalOptions="EndAndExpand">
</Button>
The other way is to put the command in your CardViewModel (or whatever class you store in CardList) and just assing the command from ContentPageViewModel.
Another way is to add DependencyPropery to your ConentView to store your command.

MainPage not added to the Navigation Stack

I start my Xamarin.Forms android project simply by calling:
MainPage = new NavigationPage(new HomePage());
in the App.xaml.cs
As stated in the https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/navigation/hierarchical/
This causes the HomePage ContentPage instance to be pushed onto the
navigation stack, where it becomes the active page and the root page
of the application.
But when i check the stack, its empty:
What is happening here? Why the page is not in the stack?
I have simply created a new XF project.
I have changed the main page xml to this
<?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:Test" x:Class="Test.TestPage">
<StackLayout>
<Button Text="How many?" Clicked="Handle_Clicked"/>
<Label Text="Welcome to Xamarin Forms!" VerticalOptions="Center" HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
and add this to xml.cs
void Handle_Clicked(object sender, System.EventArgs e)
{
//throw new NotImplementedException();
Application.Current.MainPage.DisplayAlert("Attention", Navigation.NavigationStack.Count.ToString(), "Ok");
}
and I see that NavigationStack's Count is 1...
UPDATE
Also with a CarouselPage, I have the same result
<?xml version="1.0" encoding="UTF-8"?>
<CarouselPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Test.TestPage">
<ContentPage>
<StackLayout>
<Button Text = "how many?" Clicked="Handle_Clicked"/>
<Label Text="Red" />
<BoxView Color="Red" VerticalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>
<ContentPage>
<StackLayout>
<Label Text="Green" />
<BoxView Color="Green" VerticalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>
<ContentPage>
<StackLayout>
<Label Text="Blue" />
<BoxView Color="Blue" VerticalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>
</CarouselPage>

Xamarin No property, bindable property, or event found for 'ToolbarItems'

What i was trying to do is adding toolbar to a content page.
after adding this code under StackLayout
<ContentPage.ToolbarItems>
<ToolbarItem Icon="plus.png"/>
</ContentPage.ToolbarItems>
for additional info. if i put the upper code in same position as top StackLayout the toolbar just wont appear.
i faced an error and could't find same error any where else.
this is my xaml file content.
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
xmlns:ic="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="EodiRoad.SocialPage">
<StackLayout>
<ContentPage.ToolbarItems>
<ToolbarItem Icon="plus.png"/>
</ContentPage.ToolbarItems>
<ListView x:Name="socialPostsListView" HasUnevenRows="true" IsPullToRefreshEnabled="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" Padding="5">
<StackLayout Orientation="Horizontal" Padding="5">
<ic:CircleImage
x:Name="userProfileImage"
HeightRequest="50"
WidthRequest="50"
Aspect="AspectFill"
Source="{Binding post.uploader.userProfile.userThumbnail}"
/>
<Label Text="{Binding post.uploader.username}"/>
</StackLayout>
<Image
x:Name="postImage"
Source="{Binding post.image}"
Aspect="AspectFill"
/>
<StackLayout Orientation="Horizontal">
<Button Text="like"/>
<Button Text="share"/>
</StackLayout>
<StackLayout Orientation="Vertical" HorizontalOptions="StartAndExpand">
<Label Text="{Binding post.content}"/>
<Label Text="{Binding post.uploadedTime}" TextColor="Gray"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
and this is the error.
No property, bindable property, or event found for 'ToolbarItems'
and the full error.
/Users/UZU/Google Drive/Apps/EodiRoad/EodiRoadXamarin/EodiRoad/EodiRoad/EodiRoad.Views.SocialPage.xaml(5,5): Error: Position 13:5. No property, bindable property, or event found for 'ToolbarItems' (EodiRoad)
what am i doing wrong here? and whats that error about, and how to fix it?!
i believe in you guys.
This snippet
<ContentPage.ToolbarItems>
<ToolbarItem Icon="plus.png"/>
</ContentPage.ToolbarItems>
can mean 2 things, depending on context:
Let's set the ToolbarItems property (or ToolbarItemsProperty BindableProperty) of this ContentPage (if the parent node is a ContentPage, or
Let's set the Attached BindableProperty ContentPage.ToolbarItemsProperty to the current BindableObject.
As you are using this in a StackLayout, this is interpreted as the 2nd, but such a property doesn't exists ! so it fails.
Place that directly in the ContentPage and it'll work like a charm
<ContentPage ...>
<ContentPage.ToolbarItems>
<ToolbarItem Icon="plus.png"/>
</ContentPage.ToolbarItems>
<StackLayout .../>
</ContentPage>
About the ToolbarItems not appearing, depending on the platform you are running on, it might require the ContentPage to be packed in a NavigationPage.
You need to add the ToolbarItems outside of the StackLayout Try this:
<ContentPage
xmlns:ic="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="EodiRoad.SocialPage">
<ContentPage.ToolbarItems>
<ToolbarItem Icon="plus.png"/>
</ContentPage.ToolbarItems>
<StackLayout>
<!-- Your Content -->
</StackLayout>
</ContentPage>

Categories

Resources