Dhruti
Dhruti

Reputation: 37

xamarin Forms - Is it possible to get Grid row selection event?

How do i get row id of grid row selection? I want to add row unique id and i want it on tapped or on clicked. please suggest me if anyone have any idea.

I want to do some thing like this, if i click on the row and i get id. with this id i will fetch another records and send user on another page. for this i need unique id of the row.

i have grid like bellow:

enter image description here

Below is the code i use:

    public BusList(Common busdata)
    {
        InitializeComponent();
        this.BindingContext = this;
        List<BusDetail> Bus = new List<BusDetail>
        {
            ...
            new BusDetail("Nita Travel","Mumbai", "Navsari",new DateTime(2017, 3, 9), "10:15 AM", "09:15 AM")
        };

        Label header = new Label
        {
            Text = "GridView Demo",
            FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
            HorizontalOptions = LayoutOptions.Center
        };


        var controlGrid = new Grid
        {

            RowSpacing = 2,
            ColumnSpacing = 2,
            Margin = new Thickness(5, Device.OnPlatform(5, 0, 0), 5, 5)
        };
        controlGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(30) });
        for (int i = 0; i < Bus.Count(); i++)
        {
            controlGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(30) });
        }
        controlGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
        controlGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
        controlGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
       controlGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });



        Bus = Bus.Where(x => x.FromDest.ToLower().Contains(busdata.FromDest.ToLower()) && x.FromDate == busdata.FromDate).ToList();
        controlGrid.Children.Add(new Label { Text = "ID", Font = Font.SystemFontOfSize(NamedSize.Large).WithAttributes(FontAttributes.Bold), BackgroundColor = Color.Gray }, 0, 0);
        controlGrid.Children.Add(new Label { Text = "Travel Name", Font = Font.SystemFontOfSize(NamedSize.Large).WithAttributes(FontAttributes.Bold), BackgroundColor = Color.Gray }, 1, 0);
        controlGrid.Children.Add(new Label { Text = "Arr Time", Font = Font.SystemFontOfSize(NamedSize.Large).WithAttributes(FontAttributes.Bold), BackgroundColor = Color.Gray }, 2, 0);
        controlGrid.Children.Add(new Label { Text = "Dep Time", Font = Font.SystemFontOfSize(NamedSize.Large).WithAttributes(FontAttributes.Bold), BackgroundColor = Color.Gray }, 3, 0);


        for (int i = 0; i < Bus.Count(); i++)
        {
            var clickableRow = new ContentView();

            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.SetBinding(TapGestureRecognizer.CommandProperty, "RowTappedCommand");
            tapGestureRecognizer.SetBinding(TapGestureRecognizer.CommandParameterProperty, i.ToString()); 

            clickableRow.GestureRecognizers.Add(tapGestureRecognizer);
            clickableRow.BindingContext = i.ToString();
            controlGrid.Children.Add(clickableRow, 0, i);
            Grid.SetColumnSpan(clickableRow, 3);


            controlGrid.Children.Add(new Label { Text = Bus[i].TravelName, BindingContext = Bus[i].TravelName, BackgroundColor = Color.LightGray, VerticalTextAlignment = TextAlignment.Center }, 1, i + 1);
            controlGrid.Children.Add(new Label { Text = Bus[i].ArrivalTime, BindingContext = Bus[i].ArrivalTime, BackgroundColor = Color.LightGray, VerticalTextAlignment = TextAlignment.Center }, 2, i + 1);
            controlGrid.Children.Add(new Label { Text = Bus[i].DepartureTime, BindingContext= Bus[i].DepartureTime, BackgroundColor = Color.LightGray, VerticalTextAlignment = TextAlignment.Center }, 3, i + 1);

        }
        this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);
        this.Content = new StackLayout
        {
            Children =
            {
                header,
                controlGrid
            }
        };
    }

  public  void RowTappedCommand(string index)
    {
        var tappedRow = int.Parse(index);

    }

Upvotes: 1

Views: 6018

Answers (1)

Timo Salom&#228;ki
Timo Salom&#228;ki

Reputation: 7189

You could add a ContentView to each row on the first column and span it across all columns by using the ColumnSpan property. Then you'd handle the taps with a TouchGestureListener. When creating the Command, you'd also include a CommandParameter which contains the index of the row in question.

Outside the constructor, define this:

public ICommand RowTappedCommand { get; private set; }

Then add the following code somewhere after InitializeComponent:

RowTappedCommand = new Command<string>(RowTapped);

Then create the clickable ContentView controls for each row:

var clickableRow = new ContentView {
    HorizontalOptions = LayoutOptions.FillAndExpand,
    VerticalOptions = LayoutOptions.FillAndExpand
}

var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.SetBinding(TapGestureRecognizer.CommandProperty, "RowTappedCommand");
var binding = new Binding();
binding.Source = i.ToString();
tapGestureRecognizer.SetBinding(TapGestureRecognizer.CommandParameterProperty, binding); // This is the index of the row
clickableRow.GestureRecognizers.Add(tapGestureRecognizer);

controlGrid.Children.Add(clickableRow, 0, 0);
Grid.SetColumnSpan(clickableRow,3);

You also need to define the method that matches the name defined in the CommandProperty. If you have a view model defined for the view you need to do it there. Otherwise, you'll need to add the method to your view's code behind file (xaml.cs).

void RowTapped(string index)
{
    var tappedRow = int.Parse(index);
    // Do something with the value
}

Remember to set the BindingContext correctly so that your command gets called. Here's more information about Commands in Xamarin.Forms:


Update: There were a few mistakes that needed to be fixed.

  1. Command wasn't defined correctly.
  2. The binding for the command property needs to be pointing to a static value

Simplifying Events with Commanding

Upvotes: 3

Related Questions