我有以下内容:
主窗口:
<Window x:Class="TestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestApp"
xmlns:settings="clr-namespace:TestApp.Settings"
mc:Ignorable="d" Title="MainWindow" Height="350" Width="525">
<Grid>
<ItemsControl>
<ItemsControl.ItemsSource>
<Binding>
<Binding.Source>
<CollectionViewSource Source="{Binding Source={x:Static settings:CustomSettings.Default}, Path=coll}" />
</Binding.Source>
</Binding>
</ItemsControl.ItemsSource>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBox Text="{Binding Name}" />
<Button Grid.Column="1" Click="Button_Click" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
代码隐藏:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace TestApp
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
if (Settings.CustomSettings.Default.coll == null)
{
Settings.CustomSettings.Default.coll = new ObservableCollection<BasicClass>();
Settings.CustomSettings.Default.coll.Add(new BasicClass("String1"));
Settings.CustomSettings.Default.coll.Add(new BasicClass("String2"));
Settings.CustomSettings.Default.coll.Add(new BasicClass("String3"));
}
Settings.CustomSettings.Default.Save();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Settings.CustomSettings.Default.Save();
foreach (BasicClass item in Settings.CustomSettings.Default.coll)
{
MessageBox.Show(item.Name);
}
}
}
public class BasicClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private string name;
public string Name
{
get { return name; }
set
{
if (value != name)
{
name = value;
NotifyPropertyChanged("Name");
}
}
}
public BasicClass() { }
public BasicClass(string Name)
{
this.Name = Name;
}
}
}
设定:
using System.Collections.ObjectModel;
using System.Configuration;
using System.Diagnostics;
namespace TestApp.Settings
{
internal sealed partial class CustomSettings : ApplicationSettingsBase
{
private static CustomSettings defaultInstance = ((CustomSettings)(Synchronized(new CustomSettings())));
public static CustomSettings Default
{
get
{
return defaultInstance;
}
}
[UserScopedSetting()]
[DebuggerNonUserCode()]
public ObservableCollection<BasicClass> coll
{
get
{
return ((ObservableCollection<BasicClass>)(this["coll"]));
}
set
{
this["coll"] = value;
}
}
}
}
工作原理:
该应用提供了三个控件,包括TextBox
和Button
。这些是ItemsControl
的一部分,其来源绑定到ObservableCollection<BasicClass>
类型的用户设置'coll'。 BasicClass
有一个属性“名称”,它通过数据绑定显示在TextBox
中。
预期行为:
我更改TextBox
中的文字,然后点击相应的Button
。然后,这将在“coll”中保存新值,然后呈现MessageBox
序列,证明这确实已经改变。我重启了应用程序,我的值显示了新保存的值。
实际行为:
我更改了文字,单击Button
,MessageBox
序列显示该值现在存储在用户设置中(因此应该已保存)。但是,当我重新启动应用程序时,我会看到原始值,而不是已保存的值。
异常(?):
如果我单击按钮两次而不是一次(通过MessageBox
序列两次),当我重新启动时,该值现已成功保存。
答案 0 :(得分:1)
编辑(以下原始答案):
虽然我怀疑在ObservableCollection 的子类上实现IBindableComponent,但我不推荐它。如果您只是存储字符串,System.Collections.Specialized.StringCollection可能会帮助您。
但总的来说,每次发生变化时,我都认为更新应用程序设置没有多大意义。而是在应用程序启动期间将它们加载到视图模型(例如ObservableCollection)中,并在关闭时将它们移回应用程序设置。这样,只需要对值进行反序列化和序列化一次。
您在评论中提到的关于将值设置为自身的效果(看起来很有效),因为在设置列表时会重新序列化列表。看来,ApplicationSettingsBase正在存储您提供的每个值的序列化副本,因此无法对原始对象的更改做出反应。再次提供该值时,它将使用对象的新状态的序列化版本覆盖其副本。但是,如果每次用户进行更改时序列化列表,一旦列表变长,它将影响应用程序的性能。
这对你来说也很有趣: How to store int[] array in application Settings
似乎没有必要自己继承ApplicationSettingsBase,请参阅https://social.msdn.microsoft.com/Forums/en-US/4e299ed8-8e3a-408e-b900-eb6738fe0775/persist-and-restore-application-state?forum=wpf
ORIGINAL:
我不熟悉ApplicationSettingsBase,但这可能有助于https://msdn.microsoft.com/en-in/library/8eyb2ct1(en-us).aspx:
您只能将应用程序设置绑定到支持IBindableComponent接口的组件。此外,组件必须为特定绑定属性实现更改事件,或通过INotifyPropertyChanged接口通知属性已更改的应用程序设置。 如果组件未实现IBindableComponent并且您通过Visual Studio进行绑定,则绑定属性将首次设置,但不会更新。如果组件实现了IBindableComponent但不支持属性更改通知,则在更改属性时,绑定将不会在设置文件中更新。
这似乎与仅存储设置的序列化版本这一事实有关,因此无法识别列表中的更改(因为引用本身不会更改)。请注意,单击按钮完全替换列表后,将存储新列表的值。