Mirwais
Mirwais

Reputation: 131

How to access CommandParameter in codebehind?

I am using a ListView to display the titles of 'assignments' that I get from an API. Once I click on an assignment, I want to go to the details page of this assignment. Here I want to show the description and id of the selected assignment. I have this all almost figured out, but I am stuck.

My XAML page looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="App.Views.AssignmentListPage"
         Title="Opdrachten">
<ListView x:Name="AssignmentsListView" Margin="20">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Padding="20,0,0,0" HorizontalOptions="StartAndExpand" Orientation="Horizontal">
                    <Label Text="{Binding Title}" VerticalTextAlignment="Center">
                        <Label.GestureRecognizers>
                            <TapGestureRecognizer Tapped="OnLabelClicked" CommandParameter="{Binding .}"/>
                        </Label.GestureRecognizers>
                    </Label>
                    <!--<Label Text="{Binding Title}" VerticalTextAlignment="Center">
                        <Label.GestureRecognizers>
                            <TapGestureRecognizer Command="viewDetails" CommandParameter="{Binding .}"/>
                        </Label.GestureRecognizers>
                    </Label>-->
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

My code-behind looks like this:"

public partial class AssignmentListPage : ContentPage
{
    public AssignmentListPage ()
    {
        InitializeComponent ();
    }

    protected override async void OnAppearing()
    {
        base.OnAppearing();

        AssignmentsListView.ItemsSource = await App.AssignmentManager.GetAssignmentsAsync();

    }

    async void OnLabelClicked(object s, EventArgs e)
    {

        var a = e.ToString();

        var assignment = new Assignment
        {
            Id = "1234",
            Title = "Cross-Platform Application",
            Description = "What a beautiful description"
        };

        var assignmentDetailsPage = new AssignmentDetailsPage
        {
            BindingContext = assignment
        };

        await Navigation.PushAsync(assignmentDetailsPage);
    }


}

As you can see, I've hard-coded the id, title, and description in the OnLabelClicked function. I want to use e.Parameter to get these data, but that is not something I can select. I can only choose from ToString, Equals, getType. But when I run the application and inspect e, it does contains 'Parameter`. See picture.

enter image description here

I've tried using Command instead of Tapped in the XAML file, but without success. I couldn't find out how to do that.

I am new to all of this and I've been working all day on this issue. I got a little bit of tunnel vision. I hope you guys can point me in the right direction.

Upvotes: 0

Views: 1600

Answers (2)

Dominic P
Dominic P

Reputation: 2901

You are mixing two different user interaction patterns that aren't intended to be mixed. You can go the route @Jason suggests and use the event pattern, which would be equivalent to the event-driven paradigms used in lots of UI frameworks, including WinForms. It is fully supported in XAML-based frameworks (WPF, Xamarin, etc.) as well, but it's worth understanding the command pattern as well.

The command pattern is build for a more declarative usage model and is a part of the MVVM model of application development. The idea is that you use data binding to create looser connections between front-end views and the objects (in this case called a view-model) that back them.

Whereas in event patterns you would wire up event handlers which get called via .NET delegates, commands are classes deriving from ICommand, and objects of these types are used both the execute the desired logic as well as to do things like indicate state (whether the command can be invoked at the current time or not).

In this case, you'd bind an ICommand object (usually a bindable property of your view-model) to the Command property of your TapGestureRecognizer and the value you want to pass to the CommandParameter property. Upon invocation, the CommandParameter will be passed to the Execute method of the Command object.

For more complete code samples, refer to the linked articles (the first one, on commanding in Xamarin, in particular).

However, you can indeed go back to the tried-and-true event-based model of interaction if you want. There are pros and cons to each.

Upvotes: 0

Jason
Jason

Reputation: 89082

ListView has built-in ItemTapped and ItemSelected events that will do what you want

<ListView x:Name="AssignmentsListView" Margin="20" ItemSelected="OnItemSelect">

public void OnItemSelect(sender s, SelectedItemChangedEventArgs a) 
{
   // a.SelectedItem will be the selected Item, you need to cast it
   var item = (MyClass)a.SelectedItem;

   ...
}

Upvotes: 2

Related Questions