I am getting compile error with Image's Tapped Binding using Prism MVVM.
No property, bindable property, or event found for 'Tapped', or
mismatching type between value and property.
This is my code
<Image Source="bell.png" HeightRequest="25" WidthRequest="25" x:Name="yellowBoxView"
RelativeLayout.YConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Height,
Factor=0.018,Constant=10}"
RelativeLayout.XConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=0.85,Constant=15}">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="{Binding GetStaffAnnCommand}"></TapGestureRecognizer>
</Image.GestureRecognizers>
</Image>
How can I solve this issue?
Try and bind to the Command property instead:
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding GetStaffAnnCommand}"></TapGestureRecognizer>
</Image.GestureRecognizers>
Hope it helps & happy coding!
Related
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".
I created a Frame with a Grid inside with a Boxview and an Image, but the Frame is still too big even though I entered HeightRequest: "1".
How is it possible?
<Frame
RelativeLayout.YConstraint="{ConstraintExpression
Type=Constant,
Constant=11}"
RelativeLayout.XConstraint="{ConstraintExpression
Type=Constant,
Constant=310}"
CornerRadius="100"
HeightRequest="1"
BackgroundColor="Transparent"
xct:TouchEffect.NativeAnimation="True">
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="Graph_Clicked"/>
</Frame.GestureRecognizers>
<Grid>
<BoxView
Color="#404040"
CornerRadius="100"
Opacity="0.6"
Margin="-20"/>
<Image
Margin="-10"
Source="Chart.png"/>
</Grid>
</Frame>
I created a Frame with a Grid inside with a Boxview and an Image, but the Frame is still too big even though I entered HeightRequest: "1"
According to Jason's opinion, the Frame is expanding to fit its contents. If you want to make frame smaller, you just change set image HeightRequest and WidthRequest samller, then Frame will become smaller.
<Frame
BackgroundColor="Transparent"
CornerRadius="100"
RelativeLayout.XConstraint="{ConstraintExpression Type=Constant,
Constant=100}"
RelativeLayout.YConstraint="{ConstraintExpression Type=Constant,
Constant=0}">
<Grid>
<BoxView
CornerRadius="100"
Opacity="0.6"
Color="#404040" />
<Image
HeightRequest="50"
Source="c11.png"
WidthRequest="50" />
</Grid>
</Frame>
Remove margin - (negative). And height and width are requested in Xamarin.Forms and not set actually. Set vertical and horizontal options for controls. Then set the HeightRequest and WidthRequest. Should solve your issue.
<Frame
RelativeLayout.YConstraint="{ConstraintExpression Type=Constant, Constant=11}"
RelativeLayout.XConstraint="{ConstraintExpression Type=Constant, Constant=310}"
CornerRadius="100"
HeightRequest="100"
BackgroundColor="Transparent">
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="Graph_Clicked"/>
</Frame.GestureRecognizers>
<Grid HorizontalOptions="Center" VerticalOptions="Center">
<BoxView
Color="#404040"
CornerRadius="10"
Opacity="0.6"/>
<Image
Source="Chart.png"/>
</Grid>
</Frame>
I'm trying to add a floating action button to my page, to do so I wrapped my stack layout with a relative layout and add the FAB in the relative layout.
<ContentPage.Content>
<RelativeLayout BackgroundColor="Transparent">
<fab:FloatingActionButton
x:Name="fabBtn"
Source="plus.png"
Size="Normal"
Clicked="Handle_FabClicked"
NormalColor="Green"
RippleColor="Blue"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1, Constant=-75}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1, Constant=-75}" />
<StackLayout
Spacing="10"
Padding="5"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}">
<Label Text="Latest news/activities" FontSize="Medium" VerticalOptions="Start"/>
<ScrollView VerticalOptions="CenterAndExpand">
<ListView
x:Name="lsvActivities"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Padding="3">
<StackLayout Orientation="Vertical" HorizontalOptions="StartAndExpand">
<Label Text="{Binding title}" VerticalOptions="StartAndExpand"/>
<Label Text="{Binding date}" VerticalOptions="End"/>
</StackLayout>
<StackLayout HorizontalOptions="End" WidthRequest="100" HeightRequest="100" BackgroundColor="Blue">
<Label Text="image here"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
<Label Text="Good Mording" FontSize="Large" VerticalOptions="End" HorizontalOptions="Center"/>
</StackLayout>
</RelativeLayout>
</ContentPage.Content>
But it locks like the StackLayout is out of the boundary of the layout or something.
What is problem? and how I can display both the FAB and the StackLayout, where the floating action button should always be on top of the StackLayout elements
Are you trying to have the StackLayout occupy the entire screen (with the button on top)? If so, this part isn't going to do that:
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}">
That is placing the top left corner of the StackLayout at the bottom right of the screen.
Per the Xamarin docs:
Unlike AbsoluteLayout, RelativeLayout does not have the concept of the
moving anchor and does not have facilities for positioning elements
relative to the bottom or right edges of the layout.
In other words, AbsoluteLayout will try to adjust for you if you place something at the bottom right corner. RelativeLayout won't.
You probably want the constraints noted above on the StackLayout to be WidthConstraint and HeightConstraint, and set the XConstraint and YConstraint to 0.
And as Sven-Michael says, drop the ScrollView.
EDIT
The XAML should look like:
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}"
RelativeLayout.XConstraint="{ConstraintExpression Type=Constant,Constant=0}"
RelativeLayout.YConstraint="{ConstraintExpression Type=Constant,Constant=0}"
I am using the following XAML code to render some data in a ListView:
<ListView x:Name="myListView"
ItemsSource="{Binding myData}"
RowHeight="230">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<RelativeLayout Padding="1">
<StackLayout x:Name="stackLayoutTitle"
Padding="5"
Orientation="Vertical"
VerticalOptions="EndAndExpand"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.6}">
<Label Text="{Binding myText}"
FontSize="Medium"
FontAttributes="Bold"
TextColor="Black">
</Label>
</StackLayout>
</RelativeLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The data is rendering OK. Now, what I would like to do is to use banding for the Factor property of the RelativeYConstranit to position the respective StackLayout based on some calculation. Something like this (see the Factor property):
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor={Binding someValue}}"
But, when running the App I am getting an error.
Does anyone knows if it's possible to using binding expression for this?
Thanks.
I have this problem. "Factor" is not BindingProperty. Therefore now is not possible.
I tried a similar thing and failed to bind factor for YConstraint, here is an explanation of why it doesn't work
From the documentation:
In C#, relative constraints are defined as functions. Concepts like Factor aren't there, but can be implemented manually.
The error message I got:
Cannot assig property "Factor": Property does not exist, or is not assignable, or mismatching type between value and property
Conclusion:
There is no bindable property (note it has to be a bindable property otherwise you can not bind) Factor in the underlying code so it is not possible to bind.
I'm working with the ListView in Xamarin Forms. So far, I've displayed some data using a custom DataTemplate. Now, I would like to extend this to display the text inside/ over an image. Something like this:
This is the code, I'm using so far. However, in this case the text is over the image:
<ListView x:Name="MyListView"
ItemsSource="{Binding myData}"
RowHeight="190"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Padding="10" Orientation="Vertical">
<Label Text="{Binding Title}"
FontSize="Large"
VerticalOptions="Center"
TextColor="#31659e">
</Label>
<Image Source="http://www.someurl.com/images/image1.jpg" Aspect="AspectFill"></Image>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
How could I achieve the result of the first image?
If anyone has some example/ links/ tips how to do that, that would be very helpful.
Thanks
You can use a RelativeLayout. It would look like this in your data templates ViewCell.View
<RelativeLayout>
<!-- Background -->
<Image Source="http://www.someurl.com/images/image1.jpg" Aspect="AspectFill"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height}" />
<!-- Text -->
<StackLayout Padding="10" Orientation="Vertical" VerticalOptions="EndAndExpand"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height}" >
<Label Text="{Binding Title}"
FontSize="Large"
TextColor="#31659e">
</Label>
<Label Text="{Binding SubTitle}"
TextColor="#31659e">
</Label>
</StackLayout>
</RelativeLayout>
This stretches the image and the stacklayout to the same height and aligns the content of the StackLayout at the botttom.