Resume and modify some graphic elements present in another page - xaml

I have created a ControlTemplate in the app.xaml, defining the graphic part, only in the cs I would like to take some elements, to which I have given the name, to assign them the click event, but it signals me that they do not exist in the current context .
Someone who could kindly tell me how to please?
Someone, if possible, modify the source of the webview present in the main page, directly from app.xaml.cs
My code in the template is this:`
<Application.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="HeaderFooterTemplate"><ContentPresenter />
<StackLayout>
<BoxView HorizontalOptions="FillAndExpand" BackgroundColor="#DDDDDD" HeightRequest="2" Margin="0" />
<ScrollView Orientation="Horizontal">
<Grid RowSpacing="0">
<StackLayout Background="#c9ced6" HeightRequest="120" MinimumHeightRequest="120" Orientation="Horizontal" Grid.Row="0" Spacing="2">
<Grid WidthRequest="100" MinimumHeightRequest="120" BackgroundColor="#373B53" Padding="10" x:Name="Dashboard">
<Image Source="homeArancione" x:Name="imgDashboard" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="30" HeightRequest="30" Grid.Row="0" />
<Label Text="DASHBOARD" TextColor="#c9ced6" FontAttributes="Bold" HorizontalOptions="Center" Grid.Row="1" />
</Grid></Grid>
And in the reference page I recall it like this:
ControlTemplate="{StaticResource HeaderFooterTemplate}"
Graphically it works, but in the cs is I can't modify the texts to the labels or assign click events to the elements because it tells me that they don't exist in the current context

If you want to change the text or trigger the click event of the label in ControlTemplate, you could use the GestureRecognizers. The x:Name could not be found in the ControlTemplate directly.
<ControlTemplate x:Key="HeaderFooterTemplate">
<!--<ContentPresenter />-->
<StackLayout>
<BoxView HorizontalOptions="FillAndExpand" BackgroundColor="#DDDDDD" HeightRequest="2" Margin="0" />
<ScrollView Orientation="Horizontal">
<Grid RowSpacing="0">
<StackLayout Background="#c9ced6" HeightRequest="120" MinimumHeightRequest="120" Orientation="Horizontal" Grid.Row="0" Spacing="2">
<Grid WidthRequest="100" MinimumHeightRequest="120" BackgroundColor="#373B53" Padding="10" x:Name="Dashboard">
<Image Source="homeArancione" x:Name="imgDashboard" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="30" HeightRequest="30" Grid.Row="0" />
<Label Text="DASHBOARD" TextColor="#c9ced6" FontAttributes="Bold" HorizontalOptions="Center" Grid.Row="1">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"></TapGestureRecognizer>
</Label.GestureRecognizers>
</Label>
</Grid>
</StackLayout>
</Grid>
</ScrollView>
</StackLayout>
</ControlTemplate>
Code behind: App.xaml.cs
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
Console.WriteLine("-----------");
var label = sender as Label;
label.Text = "Hello";
}
Update:
update the text of the label as soon as the page loads, without
having to click
Xamarin provide GetTemplateChild to get a named element from a template. The GetTemplateChild method should only be called after the OnApplyTemplate method has been called. If you want to call the OnApplyTemplate method, this template should be added for the contentpage.
You could refer to the thread i done before.
Xamarin SwipeView Open Left Item In ControlTemplate

Related

XAML, Binding, Source and Path

I am learning to understand, how the binding mechanism works in XAML for .NET MAUI. I am assuming this is the same for all XAML projects, WPF, MAUI etc.
At the end is the whole XAML.
This XAML works fine:
<Button WidthRequest="150" Text="Add Activity"
Command="{Binding AddActivityEntityCommand}"
IsEnabled="{Binding IsNotBusy}"
Grid.Row="2"
Margin="8"/>
Is the reason why this works because the Button is part of the ContentPage, which has it's x:DataType set to MainPageViewModel, which is where the command lives?
The Binding is set to AddActivityEntityCommand, while the actual method signature is
async Task AddActivityEntityAsync(). How is this resolved? Since it obviously doesn't match the name, but it works. And what are the method signature requirements for this to work/being recognized?
This on the other hand, doesn't just work as easy out of the box:
<Label HorizontalOptions="End" TextColor="Red" Padding="0,0,10,0" Text="🗑"
IsVisible="{Binding IsSynchronized}">
<Label.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Source={x:Type viewmodel:MainPageViewModel},
Path=DeleteActivityCommand}" />
</Label.GestureRecognizers>
</Label>
In this context, adding Command="{Binding DeleteActivityCommand} doesn't work, because it derives its Path from <DataTemplate x:DataType="model:ActivityEntity">, I am assuming, which is the data object and not the ViewModel, where the command actually is.
The problem here is, that as soon as I enter this XAML Command="{Binding Source={x:Type viewmodel:MainPageViewModel}, Path=DeleteActivityCommand}", the CollectionView shows empty and there is an unhandled exception thrown when the view is loaded:
System.Reflection.TargetException: Object does not match target type.
The method signature for this command is this async Task DeleteActivityAsync()
What am I missing?
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="OnesieMobile.View.MainPage"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:model="clr-namespace:OnesieMobile.Model"
xmlns:viewmodel="clr-namespace:OnesieMobile.ViewModel"
x:DataType="viewmodel:MainPageViewModel"
Title="{Binding Title}">
<Grid
ColumnDefinitions="*"
RowDefinitions="20,50,50,*"
RowSpacing="0">
<Label HorizontalOptions="End" Margin="10,0,10,0" Text="{Binding CurrentDateTime}" Grid.Row="0"/>
<Entry Margin="10,0,10,0"
Grid.Row="1" x:Name="entryNewActivity"
Placeholder="New Activityssss" HeightRequest="30" Text="{Binding NewActivityTitle}" />
<Button WidthRequest="150" Text="Add Activity"
Command="{Binding AddActivityEntityCommand}"
IsEnabled="{Binding IsNotBusy}"
Grid.Row="2"
Margin="8"/>
<CollectionView
Grid.Row="3"
ItemsSource="{Binding ActivityEntities}"
SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:ActivityEntity">
<Grid Padding="10,0,10,0">
<Frame Style="{StaticResource CardView}">
<Grid ColumnDefinitions="*,30,50">
<StackLayout Padding="10,5,0,0" Grid.Column="0">
<Label Text="{Binding Title}" />
</StackLayout>
<StackLayout Padding="10,5,0,0" Grid.Column="1">
<Label HorizontalOptions="End" TextColor="Red"
Padding="0,0,10,0" Text="🗑" IsVisible="{Binding IsSynchronized}" >
<Label.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Source={x:Type viewmodel:MainPageViewModel},
Path=DeleteActivityCommand}" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
<StackLayout Padding="10,5,0,0" Grid.Column="2">
<Label HorizontalOptions="End"
Padding="0,0,10,0" Text="✔" IsVisible="{Binding IsSynchronized}" />
</StackLayout>
</Grid>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<ActivityIndicator IsVisible="{Binding IsBusy}"
IsRunning="{Binding IsBusy}"
HorizontalOptions="FillAndExpand"
VerticalOptions="CenterAndExpand"
Grid.RowSpan="3"
Grid.ColumnSpan="2"/>
</Grid>
</ContentPage>
Update:
MainPageViewModel.cs contains these Commands
[ICommand]
async Task DeleteActivityAsync()
{
}
[ICommand]
async Task AddActivityEntityAsync()
{
}
Inside an item template, there are several ways to refer to the original BindingContext. I like to do it by getting it from the collection itself:
<CollectionView x:Name="myCollection" ...>
...
<CollectionView.ItemTemplate>
...
Command="{Binding Source={x:Reference myCollection},
Path=BindingContext.DeleteActivityCommand}" />
FUTURE TBD:
I don't like the command name not existing anywhere in the implementing code. Hopefully there will eventually be a way to specify the command name in the ICommand attribute, to make it obvious:
// This won't work today.
[ICommand Name="DeleteActivityCommand"]
...
For now, we have to learn [ICommand]'s magic naming rules, which seem to be "Remove Async from end (if present); Add Command to end".

Xamarin.Forms - My ControlTemplate doesn't respect HeightRequest

I have created a BottomBar in my App.xaml and I am using ControlTemplate to call it into the Xaml file of a different page.
My problem is: I have tried using HeightRequest inside the Layout in my App.xaml file, also tried using it in the Xaml file of the other page when calling it, and nothing seems to work. The page doesn't respect the HeightRequest.
I want them all to have the same height on every page (60).
page1
page2
page3
As you can see, the bottom bar has a different size on each page.
My App.xaml:
<ControlTemplate x:Key="CartTemplate" >
<AbsoluteLayout
x:Name="CartSection"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
BackgroundColor="#004EFF"
HeightRequest="60">
<Image Source="caricon"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
AbsoluteLayout.LayoutBounds="0.5,0.5"
AbsoluteLayout.LayoutFlags="PositionProportional"/>
<Grid
HeightRequest="22"
IsVisible="{TemplateBinding BindingContext.OrderCountVisible}"
WidthRequest="22"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
AbsoluteLayout.LayoutBounds="0.5,0.5"
AbsoluteLayout.LayoutFlags="PositionProportional"
Padding="25,0,0,10">
<Ellipse Fill="White"/>
<Label
Text="{TemplateBinding BindingContext.cartNumberItems}"
HorizontalOptions="CenterAndExpand"
TextColor="#004EFF"
FontAttributes="Bold"
FontSize="14"
Padding="0,0,0,3"
FontFamily="{StaticResource Helvetica}"/>
</Grid>
<AbsoluteLayout.GestureRecognizers>
<TapGestureRecognizer Command="{TemplateBinding BindingContext.CarCommand}" />
</AbsoluteLayout.GestureRecognizers>
</AbsoluteLayout>
</ControlTemplate>
This is how I am calling the Template (At the bottom just above the end tags):
<TemplatedView ControlTemplate="{StaticResource CartTemplate}"/>
</StackLayout>
</ContentPage.Content>
Thanks in advance.

In UWP show selected item in Flex layout for Xamarin.forms

I am showing a list in FlexLayout by BindableLayout. I want to show some background color when someone selected an item. It seems really difficult in UWP.
<FlexLayout x:Name="FlexTypes" Wrap="Wrap" Margin="0" HorizontalOptions="FillAndExpand" BindableLayout.ItemsSource="{Binding Items}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout HeightRequest="120" WidthRequest="150">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference Page}, Path=BindingContext.AddItemCommand}" CommandParameter="{Binding .}"/>
</StackLayout.GestureRecognizers>
<Frame Margin="5" Padding="0" CornerRadius="10" BackgroundColor="#f1f5fb" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Margin="0,20,0,0">
<Label Text="{Binding Name}" FontAttributes="Bold" HorizontalOptions="CenterAndExpand"/>
<Frame BackgroundColor="#ffffff" Padding="0" HeightRequest="30" WidthRequest="50" VerticalOptions="EndAndExpand" Margin="20">
<Label Text="{Binding Price, StringFormat='₹ {0:N}'}" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"/>
</Frame>
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
I am showing a list in FlexLayout by BindableLayout. I want to show some background color when someone selected an item.
For your requirement, we suggest handle it within TapGestureRecognizer Tapped event and make a previous value to record clicked item. Then set it background color as default when next item click. For more please refer the following sample code.
private Layout previous;
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
if (previous != null)
{
previous.BackgroundColor = Color.White;
}
var stacklayout = sender as Layout;
stacklayout.BackgroundColor = Color.Red;
previous = stacklayout;
}
Xaml
<FlexLayout
x:Name="FlexTypes"
Margin="0"
HorizontalOptions="FillAndExpand"
Wrap="Wrap">
<BindableLayout.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>1</x:String>
<x:String>2</x:String>
<x:String>3</x:String>
<x:String>4</x:String>
<x:String>5</x:String>
</x:Array>
</BindableLayout.ItemsSource>
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout HeightRequest="120" WidthRequest="150">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</StackLayout.GestureRecognizers>
<Label Text="{Binding}" />
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</FlexLayout>

Bind BackgroundColor of a view inside DataTemplate Xamarin.Forms

I have a list view with a DataTemplate and inside it I have a StackLayout that I need set its background but the color of it is inside a variable...When I programmatically set the background of an object using this variable color it works, but when I try to use "binding" in xaml it doesn't work and I can't get this stack programmatically because it's inside a data template...
I really need your answer..
Some help?
<ListView.ItemTemplate>
<DataTemplate>
<!--<DataTemplate.Triggers>
<DataTrigger Binding="{Binding fundoColor}" Value="4">
<Setter TargetName="produtos_stack_color" Property="Background" Value="LawnGreen" />
</DataTrigger>
</DataTemplate.Triggers>-->
<ViewCell>
<StackLayout x:Name="produtos_stack_color" BackgroundColor="{Binding fundoColor}" VerticalOptions="FillAndExpand" Margin="10,10,10,10">
<StackLayout Orientation="Horizontal" Padding="10,10,10,10" BackgroundColor="Black" HorizontalOptions="FillAndExpand">
<Image Source="{Binding imagem}" HeightRequest="80" HorizontalOptions="CenterAndExpand" WidthRequest="160" Aspect="Fill"/>
<StackLayout Orientation="Horizontal" BackgroundColor="Green" VerticalOptions="Center" HorizontalOptions="CenterAndExpand">
<Label Style="{StaticResource labelsfont}" Text="R$" FontSize="Medium" TextColor="White"/>
<Label Style="{StaticResource labelsfont}" Text="{Binding valor}" FontAttributes="Bold" FontSize="Large" TextColor="White"/>
</StackLayout>
</StackLayout>
<StackLayout Margin="0,0,0,10">
<Label Text="{Binding nome}" Style="{StaticResource labelsfont}" FontAttributes="Bold" FontSize="Medium" TextColor="White" VerticalOptions="StartAndExpand" HorizontalOptions="Center"/>
<ContentView BackgroundColor="Chartreuse" HorizontalOptions="FillAndExpand">
<Label Style="{StaticResource labelsfont}" Text="{Binding observacao}" TextColor="White" Margin="10,10,10,10" HorizontalOptions="Center" />
</ContentView>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
I heard about triggers...but I really don't know how it works exactly...
I need produtos_stack_color receive the color
My global variable in code behind...It is setted just in construct of my class
InitializeComponent();
fundoColor = Color.FromHex(this.categEscolhida.corFundo);
You can only bind with properties - so you will have to create a property in code-behind class.
public Color FundoColor { get { return fundoColor; } }
Secondly, in order to refer this property in XAML - you can use Reference extension, and specify parent as Source. For e.g.:
<StackLayout x:Name="produtos_stack_color"
BackgroundColor="{Binding FundoColor, Source={x:Reference ParentHost}}" ..>
And, make sure to set x:Name attribute in root node of your XAML. For e.g:
<ContentPage x:Name="ParentHost" .. />

Disabling highlight on listView click for xaml Page Xamarin.Forms

I have List in xaml Page:
<ListView x:Name="ListTypeView" ItemsSource="{Binding ResourceType}" BackgroundColor="#FFFFFF" HeightRequest="210" WidthRequest="300" HorizontalOptions="CenterAndExpand" RowHeight="30">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout StyleId="Settings_StackLayout" Orientation="Horizontal" Padding="0" Margin="50,0,0,0">
<Label FontSize="Medium" HorizontalOptions="StartAndExpand" Text="{Binding ResourceType}" TextColor="Black" VerticalOptions="Center" WidthRequest="100"></Label>
<Image x:Name="Image" Source="{Binding Checkbox}" HorizontalOptions="StartAndExpand" WidthRequest="18" HeightRequest="18">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference ListTypeView}, Path=BindingContext.ListTypeChangeCommand}" CommandParameter="{Binding .}"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I want to disabling highlight on listView click
(remove list Selector which is blue in color default)
The way you do it if you define TapGestureRecognizer on image then if you tap an image your list item should not be selected anyway. If you want to disable selector on item tap then you need to use different event - list item tapped
lstItems.ItemTapped += LstItems_ItemTapped;
Then
private void LstItems_ItemTapped(object sender, ItemTappedEventArgs e)
{
//do whatever you need with selected item and reset it
((ListView)sender).SelectedItem = null;
}