Retrieving the return result from the previous ViewModel
Now it is time to deal with the Edit function. You can find the PostEditView
for specific-platform projects on my GitHub: https://github.com/yanxiaodi/MvvmCrossDemo.
Create a new class file named PostEditViewModel.cs
in the ViewModels
folder in the MvvmCrossDemo.Core
project, as shown below:
namespace MvvmCrossDemo.Core.ViewModels
{
public class PostEditViewModel : MvxViewModel<PostViewModel>
{
private readonly IPostService _postService;
private readonly IMvxNavigationService _navigationService;
private int _postId;
public PostEditViewModel(IPostService postService, IMvxNavigationService navigationService)
{
_postService = postService;
_navigationService = navigationService;
}
public override void Prepare(PostViewModel post)
{
// This is the first method to be called after construction
_postId = post.Id;
}
public override async Task Initialize()
{
// Async initialization, YEY!
await base.Initialize();
await GetPost(_postId);
}
#region Post;
private PostViewModel _post;
public PostViewModel Post
{
get => _post;
set => SetProperty(ref _post, value);
}
#endregion
private async Task GetPost(int postId)
{
var response = await _postService.GetPost(postId);
if (response.IsSuccess)
{
Post = AutoMapper.Mapper.Map<PostViewModel>(response.Result);
}
}
}
}
There are a lot of similarities between the PostDetailViewModel
and the PostEditViewModel
. We need to receive the current post id and get the data from the APIs. But for PostEditViewModel
, we need to edit the Post
and pass the result to the PostListViewModel
to update the UI.
Come back to check the IMvxNavigationService
interface. There is an interface that can return a result to the previous ViewModel
, as shown below:
Task<bool> Close<TResult>(IMvxViewModelResult<TResult> viewModel, TResult result);
And another interface to receive the result:
Task<TResult> Navigate<TViewModel, TParameter, TResult>(TParameter param, IMvxBundle presentationBundle = null, CancellationToken cancellationToken = default(CancellationToken)) where TViewModel : IMvxViewModel<TParameter, TResult>;
Open the PostEditViewModel.cs
and change the parent class of it from MvxViewModel<PostViewModel>
to MvxViewModel<PostViewModel, Post>
, that means it will return a result which is the Post
type. Add two new commands here:
#region CancelAsyncCommand;
private IMvxAsyncCommand _cancelAsyncCommand;
public IMvxAsyncCommand CancelAsyncCommand
{
get
{
_cancelAsyncCommand = _cancelAsyncCommand ?? new MvxAsyncCommand(CancelAsync);
return _cancelAsyncCommand;
}
}
private async Task CancelAsync()
{
// Implement your logic here.
await _navigationService.Close(this);
}
#endregion
#region EditPostAsyncCommand;
private IMvxAsyncCommand _editPostAsyncCommand;
public IMvxAsyncCommand EditPostAsyncCommand
{
get
{
_editPostAsyncCommand = _editPostAsyncCommand ?? new MvxAsyncCommand(EditPostAsync);
return _editPostAsyncCommand;
}
}
private async Task EditPostAsync()
{
// Implement your logic here.
var response = await _postService.UpdatePost(Post.Id, AutoMapper.Mapper.Map<Post>(Post));
if (response.IsSuccess)
{
await _navigationService.Close(this, response.Result);
}
}
#endregion
Notice that the resource will not be really updated on the server but it will be faked as if. For more details about the fake API here: https://jsonplaceholder.typicode.com.
There are two buttons to respond to the user’s action. Each of them will call the Close
method but for the Cancel
button, it will return a null as the result. When the user clicks the Ok
button, the EditPostAsync
method will post the update to the API and if the result is a success, another Close
method will be called so the MvxNavigationService
will close the current ViewModel
and return a result to the previous ViewModel
.
Then update the EditPostAsync
method in the PostListViewModel.cs
file to receive the result, as shown below:
private async void EditPostAsync(PostViewModel post)
{
var result = await _navigationService.Navigate<PostEditViewModel, PostViewModel, Post>(post);
if (result != null)
{
var target = PostList.FirstOrDefault(x => x.Post.Id == result.Id);
if (target != null)
{
target.Post.Title = result.Title;
target.Post.Body = result.Body;
}
}
}
Launch the App for the Android and the UWP. Now you can edit the Post. When you return to the PostListView
, you should notice that the Post has been updated.
We did a lot of changes in this section. Be aware of the data context of your current controls to implement the data-binding. If you found that the command does not work well, check the data context first to make sure the command is correctly binding to the control.
Last updated
Was this helpful?