#c# #android #xamarin #mvvmcross
Вопрос:
Я пытаюсь создать кнопку, которая переходит на другую страницу в MvvmCross. Приложение загружается правильно, но при нажатии кнопки ничего не происходит.
Я использую модифицированную версию проекта Bable, которая была обновлена для использования mvvmcross 8. А также урезан, чтобы содержать только то, что я считаю минимальным для перемещения между двумя моделями представления.
Вот текущий код:
Библиотека основных классов:
FirstViewModel.cs
using MvvmCross.Commands;
using MvvmCross.Navigation;
using MvvmCross.ViewModels;
namespace Babel2.Core.ViewModels {
public class FirstViewModel : MvxViewModel
{
private readonly IMvxNavigationService _navigationService;
public FirstViewModel(IMvxNavigationService navigationService)
{
_navigationService = navigationService;
}
public IMvxCommand GoCommand => new MvxCommand(() => _navigationService.Navigate<SecondViewModel>());
} }
SecondViewModel.cs
using MvvmCross.ViewModels;
namespace Babel2.Core.ViewModels
{
public class FirstViewModel : MvxViewModel
{
private readonly IMvxNavigationService _navigationService;
public FirstViewModel(IMvxNavigationService navigationService)
{
_navigationService = navigationService;
}
public IMvxCommand GoCommand => new MvxCommand(() => _navigationService.Navigate<SecondViewModel>());
}
}
Приложение.cs
using MvvmCross.IoC;
using MvvmCross.ViewModels;
namespace Babel2.Core
{
public class App : MvxApplication
{
public override void Initialize()
{
CreatableTypes()
.EndingWith("Service")
.AsInterfaces()
.RegisterAsLazySingleton();
RegisterAppStart<ViewModels.FirstViewModel>();
}
}
}
Android Progject
FirstView.axml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="Second Page Go!"
local:MvxBind="Click GoCommand" />
</LinearLayout>
SecondView.axml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="40dp"
android:text="Second View" />
</LinearLayout>
SplashScreen.axml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Loading...." />
</LinearLayout>
FirstView.cs
using Android.App;
using Android.OS;
using MvvmCross.Platforms.Android.Views;
namespace Babel2.Droid.Views
{
[Activity(Label = "View for FirstViewModel")]
public class FirstView : MvxActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.FirstView);
}
}
}
SecondView.cs
using Android.OS;
using Android.Views;
using MvvmCross.Platforms.Android.Views.Fragments;
namespace Babel2.Droid.Views
{
public class SecondView : MvxFragment
{
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView(inflater, container, savedInstanceState);
View view = inflater.Inflate(Resource.Layout.SecondView, container, false);
return view;
}
}
}
LinkerPleaseInclude.cs
using System.Collections.Specialized;
using System.Windows.Input;
using Android.App;
using Android.Views;
using Android.Widget;
using MvvmCross;
namespace Babel2.Droid
{
[Preserve(AllMembers = true)]
public class LinkerPleaseInclude
{
public void Include(Button button)
{
button.Click = (s,e) => button.Text = button.Text "";
}
public void Include(CheckBox checkBox)
{
checkBox.CheckedChange = (sender, args) => checkBox.Checked = !checkBox.Checked;
}
public void Include(Switch @switch)
{
@switch.CheckedChange = (sender, args) => @switch.Checked = !@switch.Checked;
}
public void Include(View view)
{
view.Click = (s, e) => view.ContentDescription = view.ContentDescription "";
}
public void Include(TextView text)
{
text.TextChanged = (sender, args) => text.Text = "" text.Text;
text.Hint = "" text.Hint;
}
public void Include(CheckedTextView text)
{
text.TextChanged = (sender, args) => text.Text = "" text.Text;
text.Hint = "" text.Hint;
}
public void Include(CompoundButton cb)
{
cb.CheckedChange = (sender, args) => cb.Checked = !cb.Checked;
}
public void Include(SeekBar sb)
{
sb.ProgressChanged = (sender, args) => sb.Progress = sb.Progress 1;
}
public void Include(Activity act)
{
act.Title = act.Title "";
}
public void Include(INotifyCollectionChanged changed)
{
changed.CollectionChanged = (s,e) => { var test = $"{e.Action}{e.NewItems}{e.NewStartingIndex}{e.OldItems}{e.OldStartingIndex}"; };
}
public void Include(ICommand command)
{
command.CanExecuteChanged = (s, e) => { if (command.CanExecute(null)) command.Execute(null); };
}
// public void Include(MvvmCross.Platform.IoC.MvxPropertyInjector injector)
// {
// injector = new MvvmCross.Platform.IoC.MvxPropertyInjector ();
// }
public void Include(System.ComponentModel.INotifyPropertyChanged changed)
{
changed.PropertyChanged = (sender, e) => {
var test = e.PropertyName;
};
}
}
}
Настройка.cs
using Babel2.Core;
using Microsoft.Extensions.Logging;
using MvvmCross.Platforms.Android.Core;
using Serilog.Extensions.Logging;
namespace Babel2.Droid
{
public class Setup : MvxAndroidSetup<App>
{
protected override ILoggerProvider CreateLogProvider()
{
return new SerilogLoggerProvider();
}
protected override ILoggerFactory CreateLogFactory()
{
return new SerilogLoggerFactory();
}
}
}
Брызговик.cs
using Android.App;
using Android.Content.PM;
using MvvmCross.Platforms.Android.Views;
namespace Babel2.Droid
{
[Activity(
Label = "Babel2.Droid"
, MainLauncher = true
, Icon = "@drawable/icon"
, Theme = "@style/AppTheme"
, NoHistory = true
, ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashScreen : MvxSplashScreenActivity
{
public SplashScreen()
: base(Resource.Layout.SplashScreen)
{
}
}
}
Ответ №1:
Вам нужно соединить модель представления с представлением, в вашем случае это будет:
public class FirstView : MvxActivity<FirstViewModel>
И для вашего второго взгляда то же самое:
public class SecondView : MvxFragment<SecondViewModel>
Не забудьте проверить репозиторий Playground, чтобы узнать, как использовать фреймворк. Кроме того, вы можете проверить репо образцов Star Wars.
С другой стороны, не забудьте добавить атрибуты презентации к каждому представлению, пожалуйста, ознакомьтесь с официальными документами о представителях Android — представлений.
Комментарии:
1. Отлично работает, я обнаружил, что secondView должен наследовать
MvxActivity
, а неMvxFragment