【发布时间】:2018-10-23 10:29:54
【问题描述】:
假设我们有一个 MvvmCross 6.0.1 原生应用,其中包含一个包含 BottomNavigationView 的 Android Activity,其实现方式与 this blog post by James Montemagno 相同,但没有导航和替换片段。
我想做的是将BottomNavigationView 项目绑定到 ViewModel 中的 MvxCommands(或 MvxAsyncCommands),以便在多个 ViewModel 之间导航。
我应该应用什么样的架构来实现这一目标? 我的方法是正确的还是我在做一些违反 MVVM 模式和 MvvmCross 可能性的事情?
可以在here on 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>());
【问题讨论】:
-
您好,我不确定您的问题是什么。
-
我想对我的方法发表一些评论 - 似乎有太多代码无法执行简单的导航。似乎它违反了一些基本规则并且很难维护。如果您能分享一些更好的方法,我将不胜感激。
标签: xamarin mvvm xamarin.android mvvmcross