【问题标题】:How to save changes to ObservableCollection stored in Properties.Settings如何保存对存储在 Properties.Settings 中的 ObservableCollection 的更改
【发布时间】:2017-02-10 22:07:05
【问题描述】:

玩一个简单的世界时钟程序让我遇到了一个问题,即如何在程序运行之间持久化 Clock 的自定义 ObservableCollection 对象。我可以成功保存其他设置类型,例如字符串、双精度和布尔值,但 ObservableCollection 不会在程序会话之间保存。

没有引发错误,调试器值似乎更新正常(Properties.Settings.Default.SavedClocks 计数增加),时钟添加到显示的列表中没有问题。

这个question 将我带到了下面的当前代码结构。



Settings.Designer.cs - 手动创建

[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public ObservableCollection<Clock> SavedClocks
{
    get{
        return ((ObservableCollection<Clock>)(this["SavedClocks"]));
    }
    set{
        this["SavedClocks"] = value;
    }
}

时钟类定义

[Serializable]
public class Clock : INotifyPropertyChanged
{
    public string m_LocationName { get; set; }
    public TimeZoneInfo m_TimeZone { get; set; }

    public Clock(){}

    public Clock(TimeZoneInfo tz, string name)
    {
        m_TimeZone = tz;
        m_LocationName = name;
    }

    //.... Other methods removed for brevity
}

主窗口初始化

namespace WorldClock
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            if (Properties.Settings.Default.SavedClocks == null)
            {
                Properties.Settings.Default.SavedClocks = new ObservableCollection<Clock>
                {
                    //When list is empty, default with local clock
                    new Clock(System.TimeZoneInfo.Local, System.TimeZoneInfo.Local.StandardName)
                };

                Properties.Settings.Default.Save();
            }

            lvDataBinding.ItemsSource = Properties.Settings.Default.SavedClocks;
        }
    }
}

向可观察集合添加新时钟(来自下拉列表)

private void btn_AddRegion_Click(object sender, RoutedEventArgs e)
{
    TimeZoneInfo tz = timeZoneCombo.SelectedItem as TimeZoneInfo;

    Properties.Settings.Default.SavedClocks.Add(new Clock(tz, tbx_RegionName.Text));
    Properties.Settings.Default.Save();
}

XAML - 不要认为它会有用,但这是我设置 ItemSource 的 ListView

<ListView  Name="lvDataBinding">

【问题讨论】:

  • 为了存储数据,集合不需要是可观察的。您可以在应用程序启动期间轻松地从存储的列表或数组中初始化 ObservableCollection。另请参阅这篇关于在应用程序设置中存储自定义类型的帖子:blackwasp.co.uk/customappsettings.aspx
  • @Clemens - 您链接的帖子是一个很好的来源,我已经按照信函进行操作,但不幸的是,它并没有解决我的问题,即数据在运行之间不持久。尝试不同的类型是一种选择,但我很想知道为什么我的方法没有按预期工作。谢谢
  • 你的 Clock 类应该有一个无参数的构造函数。
  • @Clemens - 实际上,我已经有了,但在发帖时不小心把它去掉了。现在发布。谢谢你的想法
  • @PortlandRunner 尝试从时钟类中删除 INPC。

标签: c# wpf


【解决方案1】:

尝试在 Settings.Designer.cs 的SavedClocks 属性中添加SettingsSerializeAs 属性,以指定集合应序列化为二进制数据:

[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.SettingsSerializeAs(System.Configuration.SettingsSerializeAs.Binary)]
[global::System.Configuration.DefaultSettingValueAttribute(null)]
public ObservableCollection<Clock> SavedClocks
{
    get
    {
        return ((ObservableCollection<Clock>)(this["SavedClocks"]));
    }
    set
    {
        this["SavedClocks"] = value;
    }
}

【讨论】:

  • 这让我克服了困难,谢谢!对于其他关注的人,我还需要在我的时钟类中将[field:NonSerialized] 添加到public event PropertyChangedEventHandler PropertyChanged;
  • 这也是为我做的!
猜你喜欢
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-02
  • 1970-01-01
  • 2023-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多