2017-09-26 44 views
0

我正在使用与MvvmCross一起运行的Xamarin项目。我想在Android中添加一个首选项视图,但我无法让它工作。Mvvmcross:无法创建偏好活动

当我尝试导航到MvxPreferenceFragment,我收到以下错误:

[0:] mvx:Diagnostic: 12.11 Activity host with ViewModelType PreferenceTest.Droid.Activities.MainPreferenceActivity is not CurrentTopActivity. Showing Activity before showing Fragment for PreferenceTest.Core.ViewModels.Fragments.PreferenceViewModel 
An unhandled exception occured. 

09-26 13:54:45.753 I/MonoDroid(12779): UNHANDLED EXCEPTION: 
09-26 13:54:45.810 I/MonoDroid(12779): System.Collections.Generic.KeyNotFoundException: Could not find view for PreferenceTest.Droid.Activities.MainPreferenceActivity 
09-26 13:54:45.810 I/MonoDroid(12779): at MvvmCross.Core.Views.MvxViewsContainer.GetViewType (System.Type viewModelType) [0x0006a] in C:\projects\mvvmcross\MvvmCross\Core\Core\Views\MvxViewsContainer.cs:72 
09-26 13:54:45.810 I/MonoDroid(12779): at MvvmCross.Droid.Support.V7.AppCompat.MvxAppCompatViewPresenter.ShowHostActivity (MvvmCross.Droid.Views.Attributes.MvxFragmentPresentationAttribute attribute) [0x00000] in C:\projects\mvvmcross\MvvmCross-AndroidSupport\MvvmCross.Droid.Support.V7.AppCompat\MvxAppCompatViewPresenter.cs:166 
09-26 13:54:45.810 I/MonoDroid(12779): at MvvmCross.Droid.Support.V7.AppCompat.MvxAppCompatViewPresenter.ShowFragment (System.Type view, MvvmCross.Droid.Views.Attributes.MvxFragmentPresentationAttribute attribute, MvvmCross.Core.ViewModels.MvxViewModelRequest request) [0x0007d] in C:\projects\mvvmcross\MvvmCross-AndroidSupport\MvvmCross.Droid.Support.V7.AppCompat\MvxAppCompatViewPresenter.cs:196 
09-26 13:54:45.810 I/MonoDroid(12779): at MvvmCross.Droid.Views.MvxAndroidViewPresenter.<RegisterAttributeTypes>b__39_2 (System.Type view, MvvmCross.Core.Views.MvxBasePresentationAttribute attribute, MvvmCross.Core.ViewModels.MvxViewModelRequest request) [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewPresenter.cs:188 
09-26 13:54:45.810 I/MonoDroid(12779): at MvvmCross.Droid.Views.MvxAndroidViewPresenter.Show (MvvmCross.Core.ViewModels.MvxViewModelRequest request) [0x00055] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewPresenter.cs:295 
09-26 13:54:45.810 I/MonoDroid(12779): at MvvmCross.Droid.Views.MvxAndroidViewDispatcher+<>c__DisplayClass2_0.<ShowViewModel>b__0() [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewDispatcher.cs:26 
09-26 13:54:45.810 I/MonoDroid(12779): at MvvmCross.Droid.Views.MvxAndroidMainThreadDispatcher.RequestMainThreadAction (System.Action action, System.Boolean maskExceptions) [0x00020] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidMainThreadDispatcher.cs:20 
09-26 13:54:45.811 I/MonoDroid(12779): at MvvmCross.Droid.Views.MvxAndroidViewDispatcher.ShowViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request) [0x00014] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewDispatcher.cs:26 
09-26 13:54:45.811 I/MonoDroid(12779): at MvvmCross.Core.Navigation.MvxNavigationService+<Navigate>d__32.MoveNext() [0x0003a] in C:\projects\mvvmcross\MvvmCross\Core\Core\Navigation\MvxNavigationService.cs:179 
09-26 13:54:45.811 I/MonoDroid(12779): --- End of stack trace from previous location where exception was thrown --- 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() [0x0000c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult() [0x00000] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at MvvmCross.Core.Navigation.MvxNavigationService+<Navigate>d__40.MoveNext() [0x00078] in C:\projects\mvvmcross\MvvmCross\Core\Core\Navigation\MvxNavigationService.cs:293 
09-26 13:54:45.811 I/MonoDroid(12779): --- End of stack trace from previous location where exception was thrown --- 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() [0x0000c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.CompilerServices.TaskAwaiter.GetResult() [0x00000] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at PreferenceTest.Core.ViewModels.FirstViewModel+<ExecutePreferences>d__8.MoveNext() [0x00026] in C:\git\PreferenceTest\PreferenceTest\PreferenceTest\PreferenceTest.Core\ViewModels\FirstViewModel.cs:28 
09-26 13:54:45.811 I/MonoDroid(12779): --- End of stack trace from previous location where exception was thrown --- 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() [0x0000c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__6_0 (System.Object state) [0x00000] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0() [0x00000] in <2e14bb2dd93a405e81838369ed72695b>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at Java.Lang.Thread+RunnableImplementor.Run() [0x00008] in <2e14bb2dd93a405e81838369ed72695b>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in <2e14bb2dd93a405e81838369ed72695b>:0 
09-26 13:54:45.811 I/MonoDroid(12779): at (wrapper dynamic-method) System.Object:a278159c-f25c-4da4-ac29-d4bae0d2de73 (intptr,intptr) 

这是我试图运行(以获取完整代码,请参考下面的GitHub的链接)代码: 首先我创建的XML文件夹内部的视图(名为preference.xml)

<?xml version="1.0" encoding="utf-8"?> 
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 
    <EditTextPreference android:title="Your Name" 
         android:key="username" 
         android:summary="Please provide your username"></EditTextPreference> 
    <CheckBoxPreference android:title="Application Updates" 
         android:defaultValue="false" 
         android:summary="This option if selected will allow the application to check for latest versions." 
         android:key="applicationUpdates" /> 
    <ListPreference  android:title="Download Details" 
         android:summary="Select the kind of data that you would like to download" 
         android:key="downloadType" 
         android:defaultValue="1" 
         android:entries="@array/listArray" 
         android:entryValues="@array/listValues" /> 
    <CheckBoxPreference 
    android:key="prefer wifi" 
    android:title="Prefer WiFi" /> 
</PreferenceScreen> 

另外的片段代码:

[MvxFragmentPresentation(typeof(MainPreferenceActivity), Resource.Id.content_frame, true)] 
[Register(nameof(PreferenceFragment))] 
public class PreferenceFragment : MvxPreferenceFragment<PreferenceViewModel> 
{ 
    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    { 
     base.OnCreateView(inflater, container, savedInstanceState); 
     var view = this.BindingInflate(Resource.Xml.preferences, container, false); 
     return view; 
    } 
} 

电话可以拨出与导航服务:

private async void ExecutePreferences() 
{ 
    await _navigationService.Navigate<PreferenceViewModel>(); 
} 

我找不到什么是错,此代码:)。

这里也是样本的a github link

回答

3

第一个问题是使用MvxFragmentPresentation第一个参数是用于主机活动的ViewModel的类型,而不是活动本身的类型。你的情况是MainPreferenceViewModel

下一个问题是,因为您正在使用MvxAppCompatViewPresenter演示者,所以您需要使用MvxPreferenceFragmentCompat。可以在MvvmCross.Droid.Support.V7.Preference NuGet包中找到MvxPreferenceFragmentCompat

[MvxFragmentPresentation(typeof(MainPreferenceViewModel), Resource.Id.content_frame)] 
[Register(nameof(PreferenceFragment))] 
public class PreferenceFragment : MvxPreferenceFragmentCompat<PreferenceViewModel> 
{ 
    public override void OnCreatePreferences(Bundle savedInstanceState, string rootKey) 
    { 
     SetPreferencesFromResource(Resource.Xml.preferences, rootKey); 
    } 
} 

最后,你需要在你的活动指定偏好的主题

<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item> 

我已经用一种材料设计主题从Xamarin.Android.Support.v14.Preference,但你可能还使用了其他的之一:

  • @style/PreferenceThemeOverlay
  • @style/PreferenceThemeOverlay.v14

有关更改的完整细节,请参阅pull request

MvxPreferenceFragmentCompat example

+1

优秀的答案! – Martijn00

+0

Thx为你好awnser :) – kevingoos