将 XAML 控件绑定到应用程序数据文件
Binding XAML control to Application Data file
我有一项服务 class,其中包含处理 ApplicatonData
的所有功能
public class AppSettings : INotifyPropertyChanged
{
private static volatile AppSettings _instance;
private ApplicationDataContainer _localData;
private ApplicationDataContainer _roamingData;
private StorageFolder _localFolder;
private StorageFolder _roamingFolder;
...
//Code to make AppSettings a singleton class.
//Using AppSettings.Instance to access public properties/methods
...
private void SaveSettings(string key, object value, bool roaming = false)
{
if (roaming)
_roamingData.Values[key] = value;
else
_localData.Values[key] = value;
}
private T ReadSetting<T>(string key, T defaultValue = default(T), bool roaming = false)
{
if (roaming)
{
if (_roamingData.Values.ContainsKey(key))
return (T)_roamingData.Values[key];
}
else if (_localData.Values.ContainsKey(key))
return (T)_localData.Values[key];
return defaultValue;
}
public async void SaveToFile<T>(T obj, string propName, bool roaming = false)
{
StorageFile file = await (roaming ? _roamingFolder : _localFolder).CreateFileAsync(propName, CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, JsonConvert.SerializeObject(obj), UnicodeEncoding.Utf8);
}
public async Task<T> LoadFromFile<T>(string propName, bool roaming = false)
{
try
{
StorageFile file = await (roaming ? _roamingFolder : _localFolder).GetFileAsync(propName);
return JsonConvert.DeserializeObject<T>(await FileIO.ReadTextAsync(file, UnicodeEncoding.Utf8));
}
catch (Exception)
{
return default;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged([CallerMemberName]string propName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
//List all setting here
public string exampleProp
{
get => ReadSetting<string>(nameof(exampleProp));
set
{
SaveSettings(nameof(movie_staging_folder), value, false);
NotifyPropertyChanged();
}
}
...
// Other properties
...
}
这适用于单值属性,例如:
<TextBox Text="{x:Bind services:AppSettings.Instance.exampleProp, Mode=TwoWay}"
... />
我的问题是绑定到多值属性。我有一个 ListView
显示用户选择的目录列表。我制作了 SaveToFile()
和 LoadFromFile()
来(反)序列化一个对象,在我的例子中是一个 ObservableCollection,并且 save/load 它作为 ApplicationData 文件夹中的一个文件。我不知道如何将其绑定到 ListView ItemsSource
.
您可以在 ObservableCollection 中声明一个 属性 以从 LoadFromFile() 接收反序列化的集合并将 属性 绑定到 listView 的 ItemsSource。
public AppSettings()
{
InitializeMyList();
}
private async void InitializeMyList()
{
myLists = await LoadFromFile<ObservableCollection<String>>("");
}
private ObservableCollection<string> myLists = new ObservableCollection<string>();
public ObservableCollection<string> MyLists
{
get {
return myLists;
}
set {
......
}
}
.xaml:
<ListView ItemsSource="{x:Bind services:AppSettings.Instance.MyLists}"></ListView>
我有一项服务 class,其中包含处理 ApplicatonData
的所有功能public class AppSettings : INotifyPropertyChanged
{
private static volatile AppSettings _instance;
private ApplicationDataContainer _localData;
private ApplicationDataContainer _roamingData;
private StorageFolder _localFolder;
private StorageFolder _roamingFolder;
...
//Code to make AppSettings a singleton class.
//Using AppSettings.Instance to access public properties/methods
...
private void SaveSettings(string key, object value, bool roaming = false)
{
if (roaming)
_roamingData.Values[key] = value;
else
_localData.Values[key] = value;
}
private T ReadSetting<T>(string key, T defaultValue = default(T), bool roaming = false)
{
if (roaming)
{
if (_roamingData.Values.ContainsKey(key))
return (T)_roamingData.Values[key];
}
else if (_localData.Values.ContainsKey(key))
return (T)_localData.Values[key];
return defaultValue;
}
public async void SaveToFile<T>(T obj, string propName, bool roaming = false)
{
StorageFile file = await (roaming ? _roamingFolder : _localFolder).CreateFileAsync(propName, CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, JsonConvert.SerializeObject(obj), UnicodeEncoding.Utf8);
}
public async Task<T> LoadFromFile<T>(string propName, bool roaming = false)
{
try
{
StorageFile file = await (roaming ? _roamingFolder : _localFolder).GetFileAsync(propName);
return JsonConvert.DeserializeObject<T>(await FileIO.ReadTextAsync(file, UnicodeEncoding.Utf8));
}
catch (Exception)
{
return default;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged([CallerMemberName]string propName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
//List all setting here
public string exampleProp
{
get => ReadSetting<string>(nameof(exampleProp));
set
{
SaveSettings(nameof(movie_staging_folder), value, false);
NotifyPropertyChanged();
}
}
...
// Other properties
...
}
这适用于单值属性,例如:
<TextBox Text="{x:Bind services:AppSettings.Instance.exampleProp, Mode=TwoWay}"
... />
我的问题是绑定到多值属性。我有一个 ListView
显示用户选择的目录列表。我制作了 SaveToFile()
和 LoadFromFile()
来(反)序列化一个对象,在我的例子中是一个 ObservableCollection,并且 save/load 它作为 ApplicationData 文件夹中的一个文件。我不知道如何将其绑定到 ListView ItemsSource
.
您可以在 ObservableCollection 中声明一个 属性 以从 LoadFromFile() 接收反序列化的集合并将 属性 绑定到 listView 的 ItemsSource。
public AppSettings()
{
InitializeMyList();
}
private async void InitializeMyList()
{
myLists = await LoadFromFile<ObservableCollection<String>>("");
}
private ObservableCollection<string> myLists = new ObservableCollection<string>();
public ObservableCollection<string> MyLists
{
get {
return myLists;
}
set {
......
}
}
.xaml:
<ListView ItemsSource="{x:Bind services:AppSettings.Instance.MyLists}"></ListView>