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
Related
In my list view, When I expand my listview I want show to many controls but when I assign Isvisible property's to label I get this error "The property "text" is shown more than once "
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="CpoLogin.MainPage">
<ListView ItemsSource="{Binding Complains}"
HasUnevenRows="True"
Margin="40,80"
ItemTapped="ListView_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding ComplainsTitle}"/>
<Label Text="Caller CNIC: 4220142488449"/>
<Label Text="Complaint Type: Emergency"/>
<Label Text="Notes: Gulshan-e-Iqal,Karachi"/>
<Label Text="Criminals Involved: 2"/>
<Label Text="Dead Count: 2"/>
<Label Text="Sub Type: Murder"/>
<Label Text="Criminal Appearance: 2"/>
<Label Text="Wounded Count: 2"/>
<Label Text="Vehicle Used: 2"
IsVisible="{Binding IsVisible}/>
<Button Text="Details"
IsVisible="{Binding IsVisible}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
#Aashir Khan
Please replace the following code
<Label Text="Vehicle Used: 2"
IsVisible="{Binding IsVisible}" />
You forgot to close the double quotes, please check and accept the answer if helps for you.
Use Content instead of text for buttons.
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.
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.
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>
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>