Binding a command to a parent view model in MAUI - xaml

I'd like to reference a parent viewmodel as a command binding.
I was expecting the MAUI syntax would work like the Xamarin does but I get the following errors:
'}' expected
'�' expected
Here is the syntax I tried:
<ContentPage ... x:Class="ParentPage" x:DataType="ParentViewModel" x:Name="Parent">
<StackLayout>
<ListView ItemsSource="{Binding Tabs}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="TabViewModel">
<ViewCell>
<Button Text="Do it"
Command="{Binding Path=SelectTab
RelativeSource={RelativeSource AncestorType={x:Type ParentPage}}}" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
Or:
<ContentPage ... x:Class="ParentPage" x:DataType="ParentViewModel" x:Name="Parent">
<StackLayout>
<ListView ItemsSource="{Binding Tabs}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="TabViewModel">
<ViewCell>
<Button Text="Do it"
Command="{Binding Path=SelectTab
Source={x:Reference Parent}}" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
What is wrong in this syntax?
Is there a specific documentation for MAUI binding?

In the first snippet, you have a comma missing and a closing brace more than needed:
<Button Text="Do it"
Command="{Binding Path=SelectTab,
RelativeSource={RelativeSource AncestorType={x:Type ParentPage}}}"
/>

Related

Carousal view with multiple items without databinding

How do I set static text as Carousal view items instead of doing data binding? Here in the below code I am trying to have Page 2 appear when the user swipes to the left. This code says The property ItemTemplate is set more than once
<StackLayout Margin="10">
<CarouselView>
<CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Label Text="Page 1"/>
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
<CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Label Text="Page 2"/>
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
If you want to set the items statically in xaml itself without data binding you can use Array markup extension of type string:
<StackLayout Margin="10">
<CarouselView>
<CarouselView.ItemsSource>
<x:Array Type="{x:Type sys:String}">
<sys:String>Page 1</sys:String>
<sys:String>Page 2</sys:String>
</x:Array>
</CarouselView.ItemsSource>
<CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Label Text="{Binding .}" />
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</StackLayout>
PS: Don't forget to add the required xaml namespace:
xmlns:sys="clr-namespace:System;assembly=mscorlib"

how to add a context menu to a list item in xamarin UWP app?

I have the following xaml code:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:GraphTutorial.Models"
Title="Shared Document Library"
x:Class="GraphTutorial.SPDocumentLibraryContentsPage">
...
...
<ListView x:Name="SharedDocumentList"
HasUnevenRows="true"
Margin="10,10,10,10"
ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Margin="10,10,10,10">
<Label Text="{Binding Path=Id}"
FontAttributes="Bold"
FontSize="Medium" />
<Label Text="{Binding Path=WebUrl}"
FontSize="Small" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Resources>
<MenuFlyout x:Name="DocumentActions">
<FlyoutItem x:Name="Edit" Text="Edit" />
<FlyoutItem x:Name="Remove" Text="Remove" Click="Remove_Click" />
</MenuFlyout>
</ListView.Resources>
</ListView>
I'm presently getting the following error message on the line:
Error XLS0414 The type 'MenuFlyout' was not found. Verify that you are
not missing an assembly reference and that all referenced assemblies
have been built.
Can someone point me in the right direction?
Thanks.
EDIT 1
I also have tried this:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:GraphTutorial.ContextMenu"
Title="Shared Document Library"
x:Class="GraphTutorial.SPDocumentLibraryContentsPage">
<ListView x:Name="SharedDocumentList"
HasUnevenRows="true"
Margin="10,10,10,10"
ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Margin="10,10,10,10">
<Label Text="{Binding Path=Id}"
FontAttributes="Bold"
FontSize="Medium" />
<Label Text="{Binding Path=WebUrl}"
FontSize="Small" />
</StackLayout>
</ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Add" Clicked="Add_Clicked"></MenuItem>
<MenuItem Text="Delete" Clicked="Delete_Clicked"></MenuItem>
<MenuItem Text="Edit" Clicked="Edit_Clicked">
</ViewCell.ContextActions>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
But this returns the error:
XLS0415 The attachable property 'ContextActions' was not found in type
'ViewCell'.
Error XLS0414 The type 'MenuFlyout' was not found. Verify that you are
not missing an assembly reference and that all referenced assemblies
have been built.
From document MenuFlyout Class,we know that class MenuFlyout is a class in uwp, so we can't use it in xamarin.
If you want to add a context menu to a list item in xamarin UWP,you can refer to the following code:
<ListView x:Name="listView" Margin="20" ItemSelected="OnListItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Margin="20,0,0,0" Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<Label Text="{Binding Name}" VerticalTextAlignment="Center" HorizontalOptions="StartAndExpand" />
<Image Source="check.png" HorizontalOptions="End" IsVisible="{Binding Done}" />
</StackLayout>
<ViewCell.ContextActions>
<MenuItem Text="Delete"
Clicked="OnDeleteClicked"/>
</ViewCell.ContextActions>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In page.xaml.cs
void OnDeleteClicked(object sender, EventArgs e)
{
TodoItem itemToDelete = ((sender as MenuItem).BindingContext as TodoItem);
// other code
}
For more detail, you can check:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/menuitem
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/menuitem#cross-platform-context-menu-behavior

How to create list view with side count like mail

Am working small Xamarin.forms application.Now i have doubt to how to count and display list items in label
like email and gmail.
I'm browsing in google various sites i did't get result
My Xaml code is below how to display count in side bar and i used grid for that sum Xaml.task error will be occur
<?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:emit="clr-namespace:System.Reflection.Emit;assembly=mscorlib"
x:Class="vMonitor.Views.HomeListView"
Title="Home List View"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
<ScrollView>
<StackLayout Orientation="Vertical">
<ListView ItemsSource="{Binding Model}" Margin="20,0,20,0"
x:Name="listView"
SeparatorVisibility="Default" SeparatorColor="Brown"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<StackLayout Orientation="Horizontal" Padding="10">
<Label Text="{Binding Name}" FontSize="20" FontFamily="TimesNewRomen" FontAttributes="None">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.TabCommand, Source={x:Reference listView}}" CommandParameter="{Binding .}"/>
</Label.GestureRecognizers>
</Label>
<Label Text="{Binding UserID}" FontSize="20" FontFamily="TimesNewRomen" FontAttributes="None"/>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ScrollView>
</ContentPage>
Then you can use ViewCell for List Item.
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="15,10" Orientation="Horizontal">
<Label
VerticalTextAlignment="Center"
Text="{Binding ItemName}" TextColor="#FF1654" FontAttributes="Bold" FontSize="16"/>
<Label VerticalOptions="End"
VerticalTextAlignment="Center"
Text="{Binding ItemCount}" TextColor="#FF1654" FontAttributes="Bold" FontSize="16"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
You can Bind ItemName and ItemCount. If you want to Display Left Side Image then you can add Image at start position in ViewCell.
For Expandable you have to use IsVisible Property for that cell.

How to add a button only once in a List View xamarin Forms

Using this code
x:Class="Fit_Plans.TimelinePage"
Title="Timeline"
BackgroundColor="{ DynamicResource MainWrapperBackgroundColor }
<ContentPage.Content>
<ListView
ItemsSource="{ Binding TimelineList }"
SeparatorVisibility="None"
BackgroundColor="{ DynamicResource BasePageColor }"
HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<StackLayout>
<Grid x:Name="GridTasks">
<local:TimelineItemTemplate
Padding="{ DynamicResource MainWrapperPadding }"/>
</Grid>
</StackLayout>
<artina:Button
Clicked="OnNextButtonTapped"
Style="{DynamicResource PrimaryActionButtonStyle}"
Text="Order"
VerticalOptions="EndAndExpand"
WidthRequest="{ artina:OnOrientationDouble
LandscapeTablet=600 }"
HorizontalOptions="{ artina:OnOrientationLayoutOptions
PortraitPhone=Fill,
LandscapePhone=Fill,
PortraitTablet=Fill,
LandscapeTablet=Center }"/>
<StackLayout>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
Result :
But if I want to display the order Button only 1 time at the end of the list view , how to achieve that?
I have tried this with no success :
<ContentPage.Content>
<ListView
ItemsSource="{ Binding TimelineList }"
SeparatorVisibility="None"
BackgroundColor="{ DynamicResource BasePageColor }"
HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<StackLayout>
<Grid x:Name="GridTasks">
<local:TimelineItemTemplate
Padding="{ DynamicResource MainWrapperPadding }"/>
</Grid>
</StackLayout>
<StackLayout>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
<artina:Button
Clicked="OnNextButtonTapped"
Style="{DynamicResource PrimaryActionButtonStyle}"
Text="Order"
VerticalOptions="EndAndExpand"
WidthRequest="{ artina:OnOrientationDouble
LandscapeTablet=600 }"
HorizontalOptions="{ artina:OnOrientationLayoutOptions
PortraitPhone=Fill,
LandscapePhone=Fill,
PortraitTablet=Fill,
LandscapeTablet=Center }"/>
It displayed the button at the end but with an empty list
ListView provides HeaderTemplate and FooterTemplate. You should put your button inside FooterTemplate as follows:
<ListView ItemsSource="{ Binding TimelineList }" SeparatorVisibility="None" BackgroundColor="{ DynamicResource BasePageColor }" HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
.................
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.FooterTemplate>
<DataTemplate>
<ContentView>
//Put your button here
</ContentView>  
</DataTemplate>  
</ListView.FooterTemplate>
</ListView>
As of previous answer you can put in in footer or if you'd want to keep he button inside the cell template then wrap the button in with a IsVisible = your custom converter, that would check if (myIndex == totalListCount) then the button would be displayed for the last item in list only.

How to set margin around ImageCell in Xamarin.Forms?

I want to have some space around the Image cell items of a ListView:
<StackLayout>
<ListView ItemsSource="{Binding Items}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell Text="{Binding Title}" ImageSource="{Binding Image}" TextColor="Black" DetailColor="Gray"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
but there's no Margin property available for the ImageCell?
EDIT
I did what cvanbeek suggested before posting the question:
<DataTemplate>
<StackLayout Padding="5">
<ImageCell Text="{Binding Title}" ImageSource="{Binding Image}" TextColor="Black" DetailColor="Gray"/>
</StackLayout>
</DataTemplate>
but I got this exception:
Unhandled Exception:
System.InvalidCastException: Specified cast is not valid.
in the OnCreate method in MainActivity.cs
DataTemplate definition
Only View can be put inside DataTemplate, however StackLayout is Layout.
Use a ViewCell instead , it is more flexible and controllable.
<ListView >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="20" Orientation="Horizontal" >
<Label Margin="20" Text="123"/>
<Image Source="Assets/StoreLogo.png"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>