0

我一直是非常棒的 Xamarin 跨平台设置插件https://components.xamarin.com/view/SettingsPlugin(准确地说是 PCL 中的 Nuget 版本)

它运行良好,但现在使用 Xamarin 表单我真的希望能够绑定到设置值。即我想在内容页面上有一个标签,上面写着:“设置值是:[值]”并在设置更改时更新。

设置类如下所示:

 public static class Settings {

   private static ISettings AppSettings
{
  get
  {
    return CrossSettings.Current;
  }
}

#region Setting Constants

    const string HOT_TIME_COUNT_KEY = "hotTimeCount";
    private static readonly int HOT_TIME_COUNT_DEFAULT = 0;



    #endregion



    public static int HotTimeCount
    {
        get { return AppSettings.GetValueOrDefault(HOT_TIME_COUNT_KEY, HOT_TIME_COUNT_DEFAULT); }
        set { AppSettings.AddOrUpdateValue(HOT_TIME_COUNT_KEY, value); }
    }

}

我似乎无法弄清楚这项工作需要什么格式?可绑定属性。创建?它是否需要 OnPropertyChanged 方法?Settings 类是否必须从 BindableObject 派生?

4

1 回答 1

2

我创建了这个库 :) 你可以随时在 github 上发布问题,但本质上你需要创建一个视图模型,其中包含你希望数据绑定到的公共属性,然后从那里调用设置并引发属性更改通知,如果值改变了。您的 Settings.cs 可以保持不变,但您需要创建视图模型,例如:

 public class MyViewModel : INotifyPropertyChanged
{

    public int Time
    {
        get { return Settings.HotTimeCount; }
        set
        {
            if (Settings.HotTimeCount == value)
                return;

            Settings.HotTimeCount = value;
            OnPropertyChanged();
        }

    }

    private Command increase;
    public Command IncreaseCommand
    {
        get 
        { 
            return increase ?? (increase = new Command(() =>Time++));
        }
    }

    #region INotifyPropertyChanged implementation

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName]string name = "")
    {
        var changed = PropertyChanged;
        if (changed == null)
            return;
        changed(this, new PropertyChangedEventArgs(name));
    }

    #endregion


}

然后您的 XAML 在您的内容页面中将如下所示:

<StackLayout Padding="25">

<Button Text="Increase" Command="{Binding IncreaseCommand}"/>
<Label Text="{Binding Time, StringFormat='The time is {0:F0}'}"/>

</StackLayout>

确保在页面的 xaml.cs 中设置 BindingContext:

public partial class MyPage : ContentPage
{
    public MyPage()
    {
        InitializeComponent();
        BindingContext = new MyViewModel();
    }
}

这实际上并没有太多实际实现的代码,因为您的 ViewModel 将更改实现 INotifyProprety 的 BaseViewModel,所以实际上您只是添加

 public int Time
    {
        get { return Settings.HotTimeCount; }
        set
        {
            if (Settings.HotTimeCount == value)
                return;

            Settings.HotTimeCount = value;
            OnPropertyChanged();
        }

    }

更神奇的方式

但是,使用 C# 的强大功能并了解数据绑定的工作原理,您可以首先创建一个所有内容都将使用的 BaseViewModel:

 public class BaseViewModel : INotifyPropertyChanged
{

    public Settings Settings
    {
        get { return Settings.Current; }
    }


    #region INotifyPropertyChanged implementation

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName]string name = "")
    {
        var changed = PropertyChanged;
        if (changed == null)
            return;
        changed(this, new PropertyChangedEventArgs(name));
    }

    #endregion


}

请注意我对Settings.Current的引用,我们现在需要将其实现为单例,但我们将使用 BaseViewModel,因此我们不必重新实现 INotifyPropertyChanged:

public class Settings : BaseViewModel
{
    static ISettings AppSettings
    {
        get
        {
            return CrossSettings.Current;
        }
    }

    static Settings settings;
    public static Settings Current
    {
        get { return settings ?? (settings = new Settings()); }
    }

    #region Setting Constants

    const string HOT_TIME_COUNT_KEY = "hotTimeCount";
    static readonly int HOT_TIME_COUNT_DEFAULT = 0;

    #endregion

    public int HotTimeCount
    {
        get
        { 
            return AppSettings.GetValueOrDefault<int>(HOT_TIME_COUNT_KEY, HOT_TIME_COUNT_DEFAULT); 
        }
        set
        { 
            if (AppSettings.AddOrUpdateValue<int>(HOT_TIME_COUNT_KEY, value))
                OnPropertyChanged();

        }
    }
}

当然,现在我们仍然希望创建一个唯一的 ViewModel,我们的 XAML 视图将绑定到:

 public class MyViewModel : BaseViewModel
{
    private Command increase;
    public Command IncreaseCommand
    {
        get 
        { 
            return increase ?? (increase = new Command(() =>Settings.HotTimeCount++));
        }
    }
}

请注意,我们现在继承自 BaseViewModel,这意味着我们的命令实际上可以增加 Settings.HotTimeCount!但是现在我们必须稍微调整一下我们的 Xaml,以了解我们为标签实际绑定的数据:

 <StackLayout Padding="25">

<Button Text="Increase" Command="{Binding IncreaseCommand}"/>
<Label BindingContext="{Binding Settings}" Text="{Binding HotTimeCount, StringFormat='The time is {0:F0}'}"/>

</StackLayout>
</ContentPage.Content>

请注意,我正在将 BindingContext 设置为我们的 Settings,该设置位于 Label 的 BaseViewModel 中,必须这样做,因为它现在位于此处。你有它。

我将使用此信息更新我的自述文件。

于 2015-10-07T05:12:36.587 回答