Xamarin Forms TableView selected item handler? - xamarin

I need to trigger a command when user clicks on the table cell.
I looked at documentation on tablecell, it doesn't talk about any click event handlers.
This is how my XAML looks -
<ContentPage Title="Default">
<TableView>
<TableView.Root>
<TableSection>
<ViewCell>
<StackLayout Padding="10,0,0,0" Orientation="Horizontal">
<Image Source="..." />
<Button Text="Home" Command="{Binding NavigateCommand}" CommandParameter="Home" />
</StackLayout>
</ViewCell>
</TableSection>
</TableView.Root>
</TableView>
</ContentPage>
Right now, command is triggered only when clicked on button, but I want to trigger command when the cell is clicked.
I am new to xamarin, is custom viewcell rendering the only way to achieve this?
If so, any pointers there?
Thanks!

You can use the Tapped gesture recognizer within a ViewCell.
Xaml:
<TableView>
<TableView.Root>
<TableSection>
<ViewCell Tapped="OnViewCellTapped">
~~~~~
</ViewCell>
</TableSection>
</TableView.Root>
</TableView>
Code behind:
protected void OnViewCellTapped(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("Tapped");
}

Related

Xamarin form carouselview scrolls with multiple items for single scroll

Iam using Carousel view control available in Xamarin form(Version 5).
In my case i used Listviews inside carousel view. It works fine if scroll by swiping to left or right, but if i programmatically set the ScrollTo or Position property for the carousel view using button click then it is scrolling multiple times though i'm setting single incremental value.
I added SnapPointsType="MandatorySingle" as mentioned here
One more issue is if my current carousel position is zero and moving to last position or more then one is not working.
<AbsoluteLayout Margin="2" BackgroundColor="Transparent">
<CarouselView
x:Name="MyCarousalView"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
Scrolled="CarouselViewScrolled">
<CarouselView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" ItemSpacing="0" SnapPointsType="MandatorySingle" />
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate>
<ListView
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
ItemsSource="{Binding .}"
x:FieldModifier="public">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Tapped="ViewCellTapped">
<StackLayout Padding="0">
<StackLayout Padding="20,1" VerticalOptions="StartAndExpand" Spacing="0" >
<Label
FontSize="16"
Text="{Binding Description}"
FontAttributes="Bold"/>
<Label
FontSize="14"
Text="{Binding CreatedDate}" />
</StackLayout>
<Label HorizontalOptions="FillAndExpand" Padding="0" HeightRequest="1" BackgroundColor="#D4D4D4"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</AbsoluteLayout>
Next button click event
private void NextClicked(object sender, EventArgs e)
{
MyCarousalView.ScrollTo((MyCarousalView.Position + 1) < _weekDaysList.Count ? MyCarousalView.Position + 1 : 0);
}
Carousel view binding:
List<List<Note>> _myList;
_myList=getData(); //based on service response
MyCarousalView.ItemsSource = null;
MyCarousalView.ItemsSource = _myList;
Screen recording with issue image
Screen video
Please letme know if any solution/workaround. Thanks

How to add entry inside picker popup? Xamarin Forms

I have a picker with more than one hundred data. I want to search a particular item. How can I add a entry inside a picker popup? Is it possible? If not, What are the best alternative to search data inside a picker?
What you want might be able to be done via custom renderer, but I personally don't know how that would be done...
If you want custom functionality in a picker, I highly recommend Rg.Plugins.Popup. This package allows a user to define there own custom popup. I use this for all my Popup pages/controls in the application I develop.
GitHub: Rg.Plugins.Popup
Define a PopupPage with an Entry and ListView and you can provide the kind of functionality you are wanting.
There is no out of the box solution for this. But a picker with searchbar can be implemented with rg.plugins.popup.(https://github.com/rotorgames/Rg.Plugins.Popup).
Create a view with label and down arrow.Provide click for that.In that click event call rg.popup.
The design of popup for referance.
<?xml version="1.0" encoding="utf-8" ?>
<pages:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="iVerify.Sample"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup"
BackgroundColor="Transparent" >
<pages:PopupPage.Animation>
<animations:ScaleAnimation
PositionIn="Center"
PositionOut="Center"
ScaleIn="1.2"
ScaleOut="0.8"
DurationIn="400"
DurationOut="300"
EasingIn="SinOut"
EasingOut="SinIn"
HasBackgroundAnimation="False"/>
</pages:PopupPage.Animation>
<StackLayout VerticalOptions="Center" Padding="10" HorizontalOptions="FillAndExpand" Margin="0,20,0,0" >
<StackLayout>
<SearchBar x:Name="Searchbar" />
</StackLayout>
<StackLayout>
<ListView x:Name="ListView" ItemsSource="{Binding}"
ItemSelected="List_Tapped">
ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
// Your controls
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</StackLayout>
</StackLayout>
</pages:PopupPage>
By using Itemselected property you can get the value of tapped view. Then set it to the label of Mainpage(label that clciked to open the popup).This can be achieved by messeging centre.
Sample screenshot
I did it with Telerik though it didn't launch on Android in main project for me and the dropdown behaves strange on UWP - it is dropping up instead of down for some layout constellations.
Telerik is not free though, so if you have it you can use:
<StackLayout Orientation="Horizontal"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<telerikInput:RadAutoCompleteView x:Name="autoCompleteView"
HorizontalOptions="FillAndExpand"
ShowSuggestionView="True"
ShowMoreItems="True"
SuggestMode="Suggest"
Watermark="Search here..." />
<Button Clicked="Button_Clicked"
Text="▼"/>
</StackLayout>
and in code behind
private void Button_Clicked(object sender, System.EventArgs e)
{
autoCompleteView.ShowSuggestions();
}

Can I use C# code to add a call to a command instead of a <Grid.GestureRecognizers>?

I have this code:
<ViewCell x:Name="co">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OpenPickerCommand}" CommandParameter="{x:Reference coPicker}" NumberOfTapsRequired="1" />
</Grid.GestureRecognizers>
<Picker x:Name="coPicker" IsVisible="false" HorizontalOptions="End" SelectedIndexChanged="coPickerSelectedIndexChanged" ItemsSource="{Binding Order}"></Picker>
<Label x:Name="coLabel" HorizontalOptions="End"/>
</Grid>
</ViewCell>
Is there a way that I can in C# connect up a command to the tapping of the cell rather than have to use the XAML <Grid.GestureRecognizers> ?
Adding a GestureRecognizer to a ViewCell is a big no-no. A ViewCell exists within a ListView or TableView which have more than enough tapped options of their own. Adding a GestureRecognizer might confuse the OS as to which tap it should handle.
Your options for the GestureRecognizer are basically the following 3, but I advise against them in a scenario where you have a ListView/TableView.
Check out some of the ListView/ViewCell based alternatives I mention below in your situation.
1. GestureRecognizer - Add it in code
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += (s, e) => {
// handle the tap
};
myGrid.GestureRecognizers.Add(tapGestureRecognizer);
2. GestureRecognizer - Use a command
When you use MVVM you can also use a command binding in C#:
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.SetBinding (TapGestureRecognizer.CommandProperty, "TapCommand");
myGrid.GestureRecognizers.Add(tapGestureRecognizer);
Which can then be bound in XAML:
<Grid>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding TapCommand}" />
</Grid.GestureRecognizers>
</Grid>
3. GestureRecognizer - Add it in XAML as you have done
<Grid>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OpenPickerCommand}" CommandParameter="{x:Reference coPicker}" NumberOfTapsRequired="1" />
</Grid.GestureRecognizers>
</Grid>
4. ViewCell - Tapped event
For the ViewCell you have a Tapped event:
<ViewCell Height="100" Tapped="OnTapped">
<ViewCell.View>
<StackLayout BackgroundColor="White" >
</StackLayout>
</ViewCell.View>
</ViewCell>
Which you can implement in code-behind:
void OnTapped (object sender, System.EventArgs e) { //your code}
5. ViewCell - Tapped command
When using MVVM you don't want to put a lot of business logic in the code-behind for your pages. In that case you can use a Behavior to convert the event to a command. A sample of that can be found here:
https://github.com/xamarin/xamarin-forms-samples/tree/master/Behaviors/EventToCommandBehavior/EventToCommandBehavior
6. ListView - ItemSelected
ListView itself also has an ItemSelected event. This can be handled the same way as the ViewCell Tapped event with both an event in code-behind or a Behavior to delegate it to a Command.
7. ListView - SelectedItem property
You can bind the SelectedItem to a property in your view model. On the setter you can perform your custom code.
<ListView
ItemsSource="{Binding YourItems}"
SelectedItem="{Binding YourSelectedItem, Mode=TwoWay}" >
</ListView>
And in code:
string _yourSelectedItem;
public string YourSelectedItem
{
get { return _yourSelectedItem; }
set {
_yourSelectedItem = value;
// Perform your custom functionality
}
}

How to implement the row clicked in Xamarin Forms TableView Cell?

I have the following tableview set up in XAML for Xamarin Forms:
<TableView Intent="Menu">
<TableRoot>
<TableSection Title="Categories">
<ViewCell>
<StackLayout Orientation="Horizontal" VerticalOptions="Center" Padding="20,0,20,0">
<Label Text="Category" XAlign="Center"/>
<Label Text=">" HorizontalOptions="EndAndExpand" XAlign="Center"/>
</StackLayout>
</ViewCell>
</TableSection>
</TableRoot>
</TableView>
Can anyone let me know how to implement the clicking of the row to open another content page xamarin forms? Or do I have to separately implement in the iOS side?
Have a look at the Xamarin Documentation about the TapGestureRecognizer.
You can apply that method here as well.
I'm not completely sure if you can apply it directly to the ViewCell but you should be able to do it on the StackLayout.
So it would be something like:
<TableView Intent="Menu">
<TableRoot>
<TableSection Title="Categories">
<ViewCell>
<StackLayout Orientation="Horizontal" VerticalOptions="Center" Padding="20,0,20,0">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapGestureRecognizerTapped"
NumberOfTapsRequired="1" />
</StackLayout.GestureRecognizers>
<Label Text="Category" XAlign="Center"/>
<Label Text=">" HorizontalOptions="EndAndExpand" XAlign="Center"/>
</StackLayout>
</ViewCell>
</TableSection>
</TableRoot>
</TableView>
And then of course implement the event method.
You could also add the Tapped method to the ViewCell itself.
Like this:
<ViewCell Tapped="Handle_Cell_Tapped">
</View>
Then write your Handle_Cell_Tapped event handler in the code behind.
You can use the ItemTappedEventArgsConverter from Xamarin.Comunity.Toolkit to do this. It's pretty simple and straight forward. Here is a link to the documentation and there are also some samples.
Xamarin Community Toolkit - ItemTappedEventArgsConverter

How to hide TableSection in Xamarin?

I have a Settings table with multiple TableSection under TableRoot:
<TableView HasUnevenRows="True" Intent="Settings">
<TableRoot>
<TableSection Title="Sec1">
<ViewCell>
<StackLayout>
<!-- Items to show, based on value SHow/Hide Sec2-->
</StackLayout>
</ViewCell>
</TableSection>
<TableSection Title="Sec2">
<ViewCell>
<StackLayout x:Name="hideLayout">
<!-- Items to hide -->
</StackLayout>
</ViewCell>
</TableSection>
</TableRoot>
</TableView>
I'm not able to dynamically show or hide the TableSection as
TableSection and ViewCell doesn't contain IsVisible property
If hideLayout.IsVisible = false; is set, then there is empty space left in this place
Please provide any suggestion to implement.

Resources