如何在MvvmCross中绑定首选项控件(SwitchPreference)?

时间:2018-04-17 20:01:39

标签: xamarin xamarin.android mvvmcross

问题

我想将SwitchPreferenceCompat上的PreferenceScreen控件的值绑定到具有MvvmCross的视图模型属性。

某些控件(如EditTextPreference)的绑定效果很好,但其他人(CheckBoxPreferenceSwitchPreferenceCompat)的绑定很不幸。我可以在调试日志中看到这些控件的属性值没有改变。

环境

我使用MvvmCross 6.0和Xamarin.Android与Visual Studio for Mac 7.4.3(版本10)。另外,我使用Xam.Plugins.Settings来存储设置。

我在运行Android 8.0的Android模拟器上运行应用程序。

实施细节/ MWW

设置片段fragment_settings.axml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <PreferenceCategory
        android:title="Basic settings">
        <SwitchPreferenceCompat
            android:key="notifications_switch"
            android:title="Switch Preference"
            android:summary="Switch Summary"
            android:defaultValue="true" />
        <CheckBoxPreference
            android:key="notifications_checkbox"
            android:title="Enable notifications"
            android:summary="Do you want to receive push notifications?"
            android:defaultValue="true" />
        <EditTextPreference
            android:key="username_edittext"
            android:title="UserName"
            android:summary="Summary"
            android:dialogMessage="Give your username if you want"
            android:defaultValue="" />
    </PreferenceCategory>
</PreferenceScreen>

SettingsView.cs

using Android.Runtime;
using App.Core.ViewModels.Main;
using App.Core.ViewModels.Settings;
using MvvmCross.Platforms.Android.Presenters.Attributes;
using MvvmCross.Droid.Support.V7.Preference;
using MvvmCross.Binding.BindingContext;
using Android.OS;
using Android.Views;
using Android.Support.V7.Preferences;

namespace App.Droid.Views.Settings
{
    [MvxFragmentPresentation(typeof(MainContainerViewModel),
                            Resource.Id.content_frame,
                            true,
                            Resource.Animation.abc_fade_in,
                            Resource.Animation.abc_fade_out,
                            Resource.Animation.abc_fade_in,
                            Resource.Animation.abc_fade_out)]
    [Register(nameof(SettingsView))]
    public class SettingsView : MvxPreferenceFragmentCompat<SettingsViewModel>// BaseFragment<SettingsViewModel>
    {
        public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            var view = base.OnCreateView(inflater, container, savedInstanceState);

            var notifPreference = (CheckBoxPreference)this.FindPreference("notifications_checkbox");
            var switchPreference = (SwitchPreferenceCompat)this.FindPreference("notifications_switch");
            var usernamePreference = (EditTextPreference)this.FindPreference("username_edittext");

            var bindingSet = this.CreateBindingSet<SettingsView, SettingsViewModel>();
            bindingSet.Bind(switchPreference)
                .For(v => v.Checked)
                .To(vm => vm.NotificationsEnabled);
            bindingSet.Bind(notifPreference)
                .For(v => v.Checked)
                .To(vm => vm.NotificationsEnabled);
            bindingSet.Bind(usernamePreference)
                .For(v => v.Text)
                .To(vm => vm.UserName);
            bindingSet.Apply();

            return view;
        }

        public override void OnCreatePreferences(Bundle savedInstanceState, string rootKey)
        {
            this.AddPreferencesFromResource(Resource.Layout.fragment_settings);
        }
    }
}

最后是视图模型本身。 SettingsViewModel.cs:

using System.Diagnostics;
using MvvmCross.Commands;
using MvvmCross.Navigation;
using Plugin.Settings;
using Plugin.Settings.Abstractions;

namespace App.Core.ViewModels.Settings
{
    public class SettingsViewModel : MvxViewModel
    {
        private readonly IMvxNavigationService _navigationService;
        private static ISettings AppSettings => CrossSettings.Current;
        public IMvxAsyncCommand CloseCommand { get; private set; }

        public SettingsViewModel(IMvxNavigationService navigationService)
        {
            Debug.WriteLine("View Settings showing");
            _navigationService = navigationService;
            CloseCommand = new MvxAsyncCommand(async () => await _navigationService.Close(this));
        }

        public string UserName
        {
            get => AppSettings.GetValueOrDefault(nameof(UserName), string.Empty);
            set
            {
                Debug.WriteLine($"Setting property Username to {value}");
                AppSettings.AddOrUpdateValue(nameof(UserName), value);
            }
        }

        public bool NotificationsEnabled
        {
            get => AppSettings.GetValueOrDefault(nameof(NotificationsEnabled), false);
            set
            {
                Debug.WriteLine($"Setting property NotificationsEnabled to {value}");
                AppSettings.AddOrUpdateValue(nameof(NotificationsEnabled), value);
            }
        }
    }
}

已经尝试

我尝试按照mvvmcross binding on switch fails on release

中的建议在LinkerPleaseInclude.cs中添加开关
    public void Include(Switch @switch)
    {
        @switch.CheckedChange += (sender, args) => @switch.Checked = !@switch.Checked;
    }

    public void Include(SwitchPreferenceCompat switchPreference)
    {
        switchPreference.PreferenceChange += (sender, args) => switchPreference.Checked = !switchPreference.Checked;
    }

1 个答案:

答案 0 :(得分:1)

我认为问题不在于您的绑定。问题似乎在于如何将视图模型属性的值应用于AppSettings。我已经能够成功获取您的首选项屏幕xml并应用视图并查看模型绑定。单击切换按钮时,viewmodel属性的值会更新。

您可以在此处检查我用于成功绑定的代码Github Repo