假设我们有一个MvvmCross 6.0.1本地应用程序,其中包含一个Android Activity,其中包含BottomNavigationView,实现方式如James Montemagno的博客文章所示,但没有导航和替换片段。
我想要做的是将BottomNavigationView项目绑定到ViewModel中的MvxCommands(或MvxAsyncCommands),以便在多个ViewModel之间导航。
我应该应用什么样的架构来实现这一点?我的方法正确吗?还是我违反了MVVM模式和MvvmCross的可能性?
可以在github上找到完整的工作示例。
我想要做的是将BottomNavigationView项目绑定到ViewModel中的MvxCommands(或MvxAsyncCommands),以便在多个ViewModel之间导航。
我应该应用什么样的架构来实现这一点?我的方法正确吗?还是我违反了MVVM模式和MvvmCross的可能性?
可以在github上找到完整的工作示例。
目前我已经使用MvxScaffolding来搭建。
MainContainerActivity
和对应的MainContainerViewModel
- 这里我想存储在视图模型之间导航的命令MainFragment
和对应的MainViewModel
- 这是第一个片段/视图模型SettingsFragment
和对应的SettingsViewModel
- 我想从MainViewModel
导航到它,反之亦然FavoritesFragment
和对应的FavoritesViewModel
主要活动如下:
using Android.App;
using Android.OS;
using Android.Views;
using PushNotifTest.Core.ViewModels.Main;
using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;
using Microsoft.AppCenter.Push;
using Android.Graphics.Drawables;
using Android.Support.Design.Widget;
using MvvmCross.Binding.BindingContext;
using System;
using System.Windows.Input;
namespace PushNotifTest.Droid.Views.Main
{
[Activity(
Theme = "@style/AppTheme",
WindowSoftInputMode = SoftInput.AdjustResize | SoftInput.StateHidden)]
public class MainContainerActivity : BaseActivity<MainContainerViewModel>
{
protected override int ActivityLayoutId => Resource.Layout.activity_main_container;
BottomNavigationView bottomNavigation;
public ICommand GoToSettingsCommand { get; set; }
public ICommand GoToFavoritesCommand { get; set; }
public ICommand GoToHomeCommand { get; set; }
protected override void OnCreate(Bundle bundle)
{
base.OnCreate();
AddBottomNavigation();
}
private void AddBottomNavigation()
{
bottomNavigation = (BottomNavigationView)FindViewById(Resource.Id.bottom_navigation);
if (bottomNavigation != null)
{
bottomNavigation.NavigationItemSelected += BottomNavigation_NavigationItemSelected;
// trying to bind command to view model property
var set = this.CreateBindingSet<MainContainerActivity, MainContainerViewModel>();
set.Bind(this).For(v => v.GoToSettingsCommand).To(vm => vm.NavigateToSettingsCommand);
set.Bind(this).For(v => v.GoToHomeCommand).To(vm => vm.NavigateToHomeCommand);
set.Bind(this).For(v => v.GoToFavoritesCommand).To(vm => vm.NavigateToFavoritesCommand);
set.Apply();
}
else
{
System.Diagnostics.Debug.WriteLine("Bottom navigation menu is null");
}
}
private void BottomNavigation_NavigationItemSelected(object sender, BottomNavigationView.NavigationItemSelectedEventArgs e)
{
try
{
System.Diagnostics.Debug.WriteLine($"Bottom navigation menu is selected: {e.Item.ItemId}");
if (e.Item.ItemId == Resource.Id.menu_settings)
if (GoToSettingsCommand != null && GoToSettingsCommand.CanExecute(null))
GoToSettingsCommand.Execute(null);
if (e.Item.ItemId == Resource.Id.menu_list)
if (GoToFavoritesCommand != null && GoToFavoritesCommand.CanExecute(null))
GoToFavoritesCommand.Execute(null);
if (e.Item.ItemId == Resource.Id.menu_home)
if (GoToHomeCommand != null && GoToHomeCommand.CanExecute(null))
GoToHomeCommand.Execute(null);
}
catch (Exception exception)
{
System.Diagnostics.Debug.WriteLine($"Exception: {exception.Message}");
Crashes.TrackError(exception);
}
}
}
}
底部导航元素为:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_home"
android:enabled="true"
android:icon="@drawable/ic_history"
android:title="@string/tab1_title"
app:showAsAction="ifRoom" />
<item
android:id="@+id/menu_list"
android:enabled="true"
android:icon="@drawable/ic_list"
android:title="@string/tab2_title"
app:showAsAction="ifRoom" />
<item
android:id="@+id/menu_settings"
android:enabled="true"
android:icon="@drawable/ic_settings"
android:title="@string/tab3_title"
app:showAsAction="ifRoom" />
</menu>
而在视图模型中的命令只有:
public IMvxAsyncCommand NavigateToSettingsCommand => new MvxAsyncCommand(async () => await _navigationService.Navigate<SettingsViewModel>());
public IMvxAsyncCommand NavigateToFavoritesCommand => new MvxAsyncCommand(async () => await _navigationService.Navigate<FavoritesViewModel>());
public IMvxAsyncCommand NavigateToHomeCommand => new MvxAsyncCommand(async () => await _navigationService.Navigate<MainViewModel>());