应用程序设置绑定最佳实践
Application settings binding best practices
一段时间以来,我一直在努力研究如何在 WinRT/UWP 应用程序的绑定级别上最好地 "interact" 设置。我一直在寻找这方面的最佳实践,但我还没有找到明确的答案。到目前为止,我在我的应用程序中所做的如下:
- 定义一个实现 INotifyPropertyChanged 的 BindableBase。
创建一个 AppSettings class,它继承自 BindableBase,看起来有点像这样:
public class AppSettings : BindableBase
{
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
public string MySetting
{
get
{
if (!localSettings.Values.ContainsKey("MySetting"))
localSettings.Values["MySetting"] = "Some default value";
return localSettings.Values["MySetting"].ToString();
}
set
{
localSettings.Values["MySetting"] = value;
RaisePropertyChanged();
}
}
}
定义一个具有 AppSettings 的 ViewModel 属性:
public class SettingsViewModel
{
public AppSettings Settings { get; set; } = new AppSettings();
}
绑定到视图中的设置属性:
<TextBlock Text="{Binding Settings.MySetting, Mode=TwoWay}">
我过去曾看到并使用过具有设置服务的实现,但这些应用程序不需要设置更改即可立即生效。所以我基本上要问的是:如果对设置的更改应该立即生效,上面的实现是绑定到设置的好方法吗?如果没有,你推荐什么?
在一般情况下这似乎没问题。我唯一要更改的是仅在数据实际更改时才发出通知:
set
{
if (MySetting != value)
{
localSettings.Values["MySetting"] = value;
RaisePropertyChanged();
}
}
这将避免不必要地发出通知。
根据读取值的频率,您可能希望在内存中保留自己的设置值副本(在私有字段中),而不是每次都从容器中读取它们。
这篇文章给我很大的启发,所以我想出了一些更优雅的东西来避免多次复制和粘贴 属性 名称(密钥)。我使用以下内容:
public class SettingsViewModel : BindableBase
{
public string MyProperty
{
get
{
return Get("MyProperty", "SomeDefaultValue");
}
set
{
Set("MyProperty", value);
}
}
public T Get<T>(string PropertyName, T DefaultValue)
{
//If setting doesn't exist, create it.
if (!App.Settings.ContainsKey(PropertyName))
App.Settings[PropertyName] = DefaultValue;
return (T)App.Settings[PropertyName];
}
public void Set<T>(string PropertyName, T Value)
{
//If setting doesn't exist or the value is different, create the setting or set new value, respectively.
if (!App.Settings.ContainsKey(PropertyName) || !((T)App.Settings[PropertyName]).Equals(Value))
{
App.Settings[PropertyName] = Value;
OnPropertyChanged(PropertyName);
}
}
}
假设您的 App
class 定义了以下 属性:
public static IPropertySet Settings
{
get
{
return Windows.Storage.ApplicationData.Current.LocalSettings.Values;
}
}
后者比写起来方便,
ApplicationData.Current.LocalSettings.Values
并且仍然可以全局访问。
一段时间以来,我一直在努力研究如何在 WinRT/UWP 应用程序的绑定级别上最好地 "interact" 设置。我一直在寻找这方面的最佳实践,但我还没有找到明确的答案。到目前为止,我在我的应用程序中所做的如下:
- 定义一个实现 INotifyPropertyChanged 的 BindableBase。
创建一个 AppSettings class,它继承自 BindableBase,看起来有点像这样:
public class AppSettings : BindableBase { ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings; public string MySetting { get { if (!localSettings.Values.ContainsKey("MySetting")) localSettings.Values["MySetting"] = "Some default value"; return localSettings.Values["MySetting"].ToString(); } set { localSettings.Values["MySetting"] = value; RaisePropertyChanged(); } } }
定义一个具有 AppSettings 的 ViewModel 属性:
public class SettingsViewModel { public AppSettings Settings { get; set; } = new AppSettings(); }
绑定到视图中的设置属性:
<TextBlock Text="{Binding Settings.MySetting, Mode=TwoWay}">
我过去曾看到并使用过具有设置服务的实现,但这些应用程序不需要设置更改即可立即生效。所以我基本上要问的是:如果对设置的更改应该立即生效,上面的实现是绑定到设置的好方法吗?如果没有,你推荐什么?
在一般情况下这似乎没问题。我唯一要更改的是仅在数据实际更改时才发出通知:
set
{
if (MySetting != value)
{
localSettings.Values["MySetting"] = value;
RaisePropertyChanged();
}
}
这将避免不必要地发出通知。
根据读取值的频率,您可能希望在内存中保留自己的设置值副本(在私有字段中),而不是每次都从容器中读取它们。
这篇文章给我很大的启发,所以我想出了一些更优雅的东西来避免多次复制和粘贴 属性 名称(密钥)。我使用以下内容:
public class SettingsViewModel : BindableBase
{
public string MyProperty
{
get
{
return Get("MyProperty", "SomeDefaultValue");
}
set
{
Set("MyProperty", value);
}
}
public T Get<T>(string PropertyName, T DefaultValue)
{
//If setting doesn't exist, create it.
if (!App.Settings.ContainsKey(PropertyName))
App.Settings[PropertyName] = DefaultValue;
return (T)App.Settings[PropertyName];
}
public void Set<T>(string PropertyName, T Value)
{
//If setting doesn't exist or the value is different, create the setting or set new value, respectively.
if (!App.Settings.ContainsKey(PropertyName) || !((T)App.Settings[PropertyName]).Equals(Value))
{
App.Settings[PropertyName] = Value;
OnPropertyChanged(PropertyName);
}
}
}
假设您的 App
class 定义了以下 属性:
public static IPropertySet Settings
{
get
{
return Windows.Storage.ApplicationData.Current.LocalSettings.Values;
}
}
后者比写起来方便,
ApplicationData.Current.LocalSettings.Values
并且仍然可以全局访问。