我正在开发我的第一个Xamarin应用程序。我试图显示我的第一页,但在base.ViewDidLoad()上收到以下错误; ViewDidLoad()中的行
已抛出MvvmCross.Platform.Exceptions.MvxException
无法从定位器MvxDefaultViewModelLocator构造和初始化类型iManage.ViewModels.LoginViewModel的ViewModel - 检查InnerException以获取更多信息
LoginView.cs:
public partial class LoginView : MvxViewController<LoginViewModel>
{
public LoginView() : base("LoginView", null)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
txtUser.Layer.CornerRadius = 15;
txtPassword.Layer.CornerRadius = 15;
btnLogin.Layer.CornerRadius = 20;
var set = this.CreateBindingSet<LoginView, LoginViewModel>();
set.Bind(txtUser).To(vm => vm.Username);
set.Bind(txtPassword).To(vm => vm.Password);
set.Bind(btnLogin).To(vm => vm.LoginCommand);
//set.Bind(btnLogin).To(vm => vm.AttemptLogin());
set.Apply();
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
}
LoginViewModel.cs:
public class LoginViewModel : BaseViewModel
{
private readonly ILoginService _loginService;
private readonly IDialogService _dialogService;
public LoginViewModel(ILoginService loginService, IDialogService dialogService)
{
_loginService = loginService;
_dialogService = dialogService;
Username = "TestUser";
Password = "YouCantSeeMe";
IsLoading = false;
}
private string _username;
public string Username
{
get
{
return _username;
}
set
{
SetProperty(ref _username, value);
RaisePropertyChanged(() => Username);
}
}
private string _password;
public string Password
{
get
{
return _password;
}
set
{
SetProperty(ref _password, value);
RaisePropertyChanged(() => Password);
}
}
private bool _isLoading;
public bool IsLoading
{
get
{
return _isLoading;
}
set
{
SetProperty(ref _isLoading, value);
}
}
private IMvxCommand _loginCommand;
public virtual IMvxCommand LoginCommand
{
get
{
_loginCommand = _loginCommand ?? new MvxCommand(AttemptLogin, CanExecuteLogin);
return _loginCommand;
}
}
private void AttemptLogin()
{
if (_loginService.Login(Username, Password))
{
ShowViewModel<DashboardEmpViewModel>();
}
else
{
_dialogService.Alert("We were unable to log you in!", "Login Failed", "OK");
}
}
private bool CanExecuteLogin()
{
return (!string.IsNullOrEmpty(Username) || !string.IsNullOrWhiteSpace(Username))
&& (!string.IsNullOrEmpty(Password) || !string.IsNullOrWhiteSpace(Password));
}
}
LoginService.cs:
public class LoginService : ILoginService
{
/// <summary>Initializes a new instance of the <see cref="LoginService"/> class.</summary>
public LoginService() // e.g. LoginService(IMyApiClient client)
{
// this constructor would most likely contain some form of API Client that performs
// the message creation, sending and deals with the response from a remote API
}
/// <summary>
/// Gets a value indicating whether the user is authenticated.
/// </summary>
public bool IsAuthenticated { get; private set; }
/// <summary>Gets the error message.</summary>
/// <value>The error message.</value>
public string ErrorMessage { get; private set; }
/// <summary>
/// Attempts to log the user in using stored credentials if present
/// </summary>
/// <returns> <see langword="true"/> if the login is successful, false otherwise </returns>
public bool Login()
{
// get the stored username from previous sessions
// var username = Settings.UserName;
// var username = _settingsService.GetValue<string>(Constants.UserNameKey);
// force return of false just for demo purposes
IsAuthenticated = false;
return IsAuthenticated;
}
/// <summary>The login method to retrieve OAuth2 access tokens from an API. </summary>
/// <param name="userName">The user Name (email address) </param>
/// <param name="password">The users <paramref name="password"/>. </param>
/// <param name="scope">The required scopes. </param>
/// <returns>The <see cref="bool"/>. </returns>
public bool Login(string userName, string password, string scope)
{
try
{
//IsAuthenticated = _apiClient.ExchangeUserCredentialsForTokens(userName, password, scope);
return IsAuthenticated;
}
catch (ArgumentException argex)
{
ErrorMessage = argex.Message;
IsAuthenticated = false;
return IsAuthenticated;
}
}
/// <summary>
/// Logins the specified user name.
/// </summary>
/// <param name="userName">Name of the user.</param>
/// <param name="password">The users password.</param>
/// <returns></returns>
public bool Login(string userName, string password)
{
// this simply returns true to mock a real login service call
return true;
}
}
Setup.cs:
public class Setup : MvxIosSetup
{
public Setup(IMvxApplicationDelegate applicationDelegate, IMvxIosViewPresenter presenter) : base(applicationDelegate, presenter)
{
}
protected override IMvxApplication CreateApp()
{
return new App();
}
}
我已使用this url来实现它。
EDIT2: 内部例外:
MvvmCross.Platform.Exceptions.MvxException:无法从定位器MvxDefaultViewModelLocator为类型iManage.ViewModels.LoginViewModel构造和初始化ViewModel - 检查InnerException以获取更多信息---&gt; MvvmCross.Platform.Exceptions.MvxException:创建LoginViewModel类型的viewModel时出现问题---&gt; MvvmCross.Platform.Exceptions.MvxIoCResolveException:创建iManage.ViewModels.LoginViewModel时,无法解析IDialogService类型的参数dialogService的参数 在MvvmCross.Platform.IoC.MvxSimpleIoCContainer.GetIoCParameterValues(System.Type type,System.Reflection.ConstructorInfo firstConstructor)[0x00066] in&lt; 6adc0d5857264558a9d45778a78ae02a&gt ;:0 在MvvmCross.Platform.IoC.MvxSimpleIoCContainer.IoCConstruct(System.Type type)[0x0002c] in&lt; 6adc0d5857264558a9d45778a78ae02a&gt ;:0 在MvvmCross.Platform.Mvx.IocConstruct(System.Type t)[0x00006] in&lt; 6adc0d5857264558a9d45778a78ae02a&gt ;:0 在MvvmCross.Core.ViewModels.MvxDefaultViewModelLocator.Load(System.Type viewModelType,MvvmCross.Core.ViewModels.IMvxBundle parameterValues,MvvmCross.Core.ViewModels.IMvxBundle savedState)[0x00000] in:0 ---内部异常堆栈跟踪结束--- 在MvvmCross.Core.ViewModels.MvxDefaultViewModelLocator.Load(System.Type viewModelType,MvvmCross.Core.ViewModels.IMvxBundle parameterValues,MvvmCross.Core.ViewModels.IMvxBundle savedState)[0x00029] in:0 在MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel(MvvmCross.Core.ViewModels.MvxViewModelRequest请求,MvvmCross.Core.ViewModels.IMvxBundle savedState)[0x00035] in:0 ---内部异常堆栈跟踪结束--- 在MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel(MvvmCross.Core.ViewModels.MvxViewModelRequest请求,MvvmCross.Core.ViewModels.IMvxBundle savedState)[0x00068] in:0 在MvvmCross.iOS.Views.MvxViewControllerExtensionMethods.LoadViewModel(MvvmCross.iOS.Views.IMvxIosView iosView)[0x0005f] in&lt; 6f99728979034e579bc72f6d53e5bc35&gt;:0 在MvvmCross.Core.Views.MvxViewExtensionMethods.OnViewCreate(MvvmCross.Core.Views.IMvxView视图,System.Func`1 [TResult] viewModelLoader)[0x00012] in:0 在MvvmCross.iOS.Views.MvxViewControllerExtensionMethods.OnViewCreate(MvvmCross.iOS.Views.IMvxIosView iosView)[0x00001] in&lt; 6f99728979034e579bc72f6d53e5bc35&gt;:0 在MvvmCross.iOS.Views.MvxViewControllerAdapter.HandleViewDidLoadCalled(System.Object sender,System.EventArgs e)[0x00007] in&lt; 6f99728979034e579bc72f6d53e5bc35&gt ;:0 at at(wrapper delegate-invoke):invoke_void_object_EventArgs(object,System.EventArgs) 在MvvmCross.Platform.Core.MvxDelegateExtensionMethods.Raise(System.EventHandler eventHandler,System.Object sender)[0x00003] in&lt; 6adc0d5857264558a9d45778a78ae02a&gt ;:0 在MvvmCross.Platform.iOS.Views.MvxEventSourceViewController.ViewDidLoad()[0x00006] in&lt; 4467c42ffcc4478e847227b8e4af47fe&gt;:0 在MvvmCross.iOS.Views.MvxViewController.ViewDidLoad()[0x00001] in&lt; 6f99728979034e579bc72f6d53e5bc35&gt;:0 at iManage.iOS.Views.LoginView.ViewDidLoad()[0x00001] in /Users/pankajsachdeva/Projects/iManage/iOS/Views/LoginView.cs:18 at at(wrapper managed-to-native)UIKit.UIApplication:UIApplicationMain(int,string [],intptr,intptr) 在UIKit.UIApplication.Main(System.String [] args,System.IntPtr principal,System.IntPtr委托)[0x00005]在/ Users / builder / data / lanes / 5665 / 6857dfcc / source / xamarin-macios / src / UIKit中/UIApplication.cs:79 在/ Users / builder / data / lanes / 5665 / 6857dfcc / source / xamarin-macios / src / UIKit中的UIKit.UIApplication.Main(System.String [] args,System.String principalClassName,System.String delegateClassName)[0x00038] /UIApplication.cs:63 at iManage.iOS.Application.Main(System.String [] args)[0x00001] in /Users/pankajsachdeva/Projects/iManage/iOS/Main.cs:17
答案 0 :(得分:0)
您必须在IoC容器中注册服务的实现,以便在需要时解析它们。一般来说,这可以在两个地方完成:
对于App.cs
方法中Initialize
的平台无关服务:
public class App : MvxApplication
{
public override void Initialize()
{
...
Mvx.ConstructAndRegisterSingleton<IDialogService,DialogService>();
...
}
}
(请注意,默认情况下应该这样做,因为默认的App
类已经包含一个块,它会自动使用&#34; Service&#34;后缀)注册所有类型
对于Setup.cs
方法中平台InitializeFirstChance
中的特定于平台的服务,例如对于Windows,它将是:
public class Setup : MvxWindowsSetup
{
protected override void InitializeFirstChance()
{
Mvx.ConstructAndRegisterSingleton<IDialogService,DialogService>();
base.InitializeFirstChance();
}
}
我猜测DialogService
将取决于平台,因此第二种解决方案会更合适。
您可以使用LazyConstructAndRegisterSingleton
确保仅在第一次实际需要时创建实例。您也可以使用RegisterType
来注册类型,并在每次需要时创建一个新实例。
有关MvvmCross IoC的更多信息available in the documentation。