Xamarin & MvvmCross Handbook
  • Introduction
  • Using MvvmCross to create your first Xamarin App
    • Creating the Core project
      • Understanding MVVM
      • Adding a simple Service
      • Adding a ViewModel
      • Adding an App class
    • Creating the Android project
      • Adding an Android Application class
      • Adding the Android Layout View (AXML)
      • Understanding the data-binding syntax
      • Adding the View class
    • Creating the iOS project
      • Updating the AppDelegate class
      • Adding the iOS View for the first ViewModel
      • Understanding the data-binding syntax
    • Creating the UWP project
      • Updating the App.xaml.cs and the App.xaml
      • Adding the UWP View
      • Understanding the data-binding syntax
    • Creating the REST API Service
      • Creating the models
      • Creating the interface and the implementation for the PostService
      • Creating the ViewModel
      • Adding the View for the Android project
      • Adding the View for the iOS project
      • Adding the View for the UWP project
    • Navigation
      • Creating the PostDetail View & ViewModel
      • Command with the parameter
      • Retrieving the param from the previous ViewModel
      • Understanding the IMvxNavigationService
      • Responding the events from different controls in the ListView
      • Retrieving the return result from the previous ViewModel
    • Creating the Xamarin.Forms project
      • Creating the Forms.UI project
      • Adding the App.xaml and the App.xaml.cs
      • Adding the View
      • Creating the Android project
      • Creating the iOS project
      • Creating the UWP project
      • Summary For Forms
    • Summary
  • Implementing MasterDetail layout in Xamarin.Forms by MvvmCross
    • Introduction
    • Creating the project by MvxScaffolding
    • Creating the MasterDetailPage
      • Creating the ViewModel
      • Creating the XAML file
    • Creating the MasterPage
      • Creating the ViewModel
      • Creating the XAML file
    • Creating the DetailPages
      • Creating the ViewModels
      • Creating the XAML files
    • Implementing the Menu functionalities
      • Displaying the MasterPage and the DetailPage
      • Setting the menu navigation
      • The other approaches to set the data-binding
    • Fine-tuning the UI
      • Adding the hamburger icon for iOS
      • Adding the header bar for Android and iOS
      • Adjust the height of the item for UWP
    • Summary
Powered by GitBook
On this page

Was this helpful?

  1. Using MvvmCross to create your first Xamarin App
  2. Navigation

Command with the parameter

Now come back to the PostListViewModel. Inject the instance of the IMvxNavigationService in the constructor, as shown below:

private readonly IPostService _postService;
private readonly IMvxNavigationService _navigationService;
public PostListViewModel(IPostService postService, IMvxNavigationService navigationService)
{
    _postService = postService;
    _navigationService = navigationService;
}

Add a new command called ShowPostDetailAsyncCommand in the PostListViewModel to respond the item click event, as shown below:

        #region ShowPostDetailAsyncCommand;
        private IMvxAsyncCommand<Post> _showPostDetailAsyncCommand;
        public IMvxAsyncCommand<Post> ShowPostDetailAsyncCommand
        {
            get
            {
                if (_showPostDetailAsyncCommand != null)
                {
                    return _showPostDetailAsyncCommand;
                }
                _showPostDetailAsyncCommand = new MvxAsyncCommand<Post>(async(post) => await ShowPostDetailAAsync(post));
                return _showPostDetailAsyncCommand;
            }
        }
        private async Task ShowPostDetailAsync(Post post)
        {
            // Implement your logic here.
            await _navigationService.Navigate<PostDetailViewModel, Post>(post);
        }
        #endregion

You can use the code snippet mvxcmdap to generate an async command. This command is an async command with a generic type Post as its param. When the user clicks the post item, I can get the current post id and pass it into the command.

For the MvvmCrossDemo.Droid project, update the data-binding in the PostListView.axml like this:

    <MvvmCross.Platforms.Android.Binding.Views.MvxListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        local:MvxBind="ItemsSource PostList; ItemClick ShowPostDetailAsyncCommand"
        android:layout_weight="1"
        local:MvxItemTemplate="@layout/post_item" />

Now the ListView is able to respond the ItemClick event and pass the context (the current Post) to the ShowPostDetailAsyncCommand.

For the MvvmCrossDemo.iOS project, it is a little complicated. We need to create a new class called PostListTableSource that inherits from MvxTableViewSource to replace the default MvxStandardTableViewSource, then override the RowSelected method to response the item click event:

public class PostListTableSource : MvxTableViewSource
{
    private static readonly NSString PostCellIdentifier = new NSString("PostCell");

    public PostListTableSource(UITableView tableView) : base(tableView)
    {
    }


    protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
    {
        var cell = TableView.DequeueReusableCell(PostCellIdentifier, indexPath);
        cell.TextLabel.Text = ((WrapperPostViewModel)item).Post.Title;
        cell.DetailTextLabel.Text = ((WrapperPostViewModel)item).Post.Body;
        return cell;
    }

    public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
    {
        base.RowSelected(tableView, indexPath);
        var item = this.SelectedItem;
        ((WrapperPostViewModel)item)?.ShowPostDetailAsyncCommand
            .Execute((WrapperPostViewModel)item);
    }
}

Then update the PostListView class like this:

[MvxFromStoryboard(nameof(PostListView))]
public partial class PostListView : MvxTableViewController<PostListViewModel>
{
    private PostListTableSource _source;
    public PostListView (IntPtr handle) : base (handle)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        _source = new PostListTableSource(TableView);
        TableView.Source = _source;

        var set = this.CreateBindingSet<PostListView, PostListViewModel>();
        set.Bind(_source).To(vm => vm.PostList);
        set.Apply();
        TableView.ReloadData();
    }
}

For the MvvmCrossDemo.Uwp project, we need to install Behaviors package first from the NuGet Package Manager. Or you can input the command below in the Package Manager Console:

Install-Package Microsoft.Xaml.Behaviors.Uwp.Managed

We use the behaviour to support event command binding. Update the codes of the PostListView.xaml, as shown below:

<views:MvxWindowsPage
    x:Class="MvvmCrossDemo.Uwp.Views.PostListView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    xmlns:i="using:Microsoft.Xaml.Interactivity"
    xmlns:core="using:Microsoft.Xaml.Interactions.Core"
    xmlns:views="using:MvvmCross.Platforms.Uap.Views">
    <Grid>
        <ListView ItemsSource="{Binding PostList}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel HorizontalAlignment="Stretch">
                            <i:Interaction.Behaviors>
                                <core:EventTriggerBehavior EventName="Tapped">
                                    <core:InvokeCommandAction Command="{Binding ShowPostDetailAsyncCommand}"></core:InvokeCommandAction>
                                </core:EventTriggerBehavior>
                            </i:Interaction.Behaviors>
                            <TextBlock Text="{Binding Post.Title}" Style="{StaticResource TitleTextBlockStyle}"></TextBlock>
                            <TextBlock Text="{Binding Post.Body}"></TextBlock>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</views:MvxWindowsPage>

You can also use some other InvokeCommandAction to bind the command of the ViewModel, for example, you can set the IsItemClickEnabled property of the ListView as True and bind the command to the ItemClick event. There is not only one approach to achieve the goal, so just select the one you like. Make sure you are clear about the DataContext of your current controls to avoid some unexpected binding errors.

PreviousCreating the PostDetail View & ViewModelNextRetrieving the param from the previous ViewModel

Last updated 6 years ago

Was this helpful?