Проблемы с сохранением коллекции объектов в настройках приложения - PullRequest
9 голосов
/ 07 октября 2011

Я пытаюсь сохранить коллекцию пользовательских объектов в настройках приложения.

С некоторой помощью этот связанный вопрос , вот что у меня сейчас есть:

// implementing ApplicationSettingsBase so this shows up in the Settings designer's 
// browse function
public class PeopleHolder : ApplicationSettingsBase
{
    [UserScopedSetting()]
    [SettingsSerializeAs(System.Configuration.SettingsSerializeAs.Xml)]
    public ObservableCollection<Person> People { get; set; }
}


[Serializable]
public class Person
{
    public String FirstName { get; set; }
}

public MainWindow()
{
    InitializeComponent();

    // AllPeople is always null, not persisting
    if (Properties.Settings.Default.AllPeople == null)
    {
        Properties.Settings.Default.AllPeople = new PeopleHolder()
            {
                People = new ObservableCollection<Person> 
                    { 
                        new Person() { FirstName = "bob" },
                        new Person() { FirstName = "sue" },
                        new Person() { FirstName = "bill" }
                    }
            };
        Properties.Settings.Default.Save();
    }
    else
    {
        MessageBox.Show(Properties.Settings.Default.AllPeople.People.Count.ToString());
    }
}

В конструкторе Settings.Settings я добавил свойство типа PeopleHolder с помощью кнопки браузера и установил область действия «Пользователь». Метод Save () завершается успешно, сообщений об ошибках нет, но при каждом перезапуске настройки приложения не сохраняются.

Хотя это и не показано в приведенном выше коде, я могу сохранить строки, но не свою собственную коллекцию (я заметил, что в других подобных вопросах на SO иногда могут возникать проблемы с номерами версий, которые не позволяют сохранить настройки при отладке, поэтому я хочу исключить это как возможного виновника.)

Есть идеи? Я уверен, что есть очень простой способ сделать это, которого мне просто не хватает :).

Спасибо за вашу помощь!

Ответы [ 2 ]

10 голосов
/ 07 октября 2011

Я понял это благодаря этому вопросу !

Как и предполагалось в этом вопросе, я добавил это в Settings.Designer.cs:

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

И затемвсе, что мне было нужно, это следующий код:

[Serializable]
public class Person
{
    public String FirstName { get; set; }
}

public MainWindow()
{
    InitializeComponent();

    // this now works!!
    if (Properties.Settings.Default.AllPeople == null)
    {
        Properties.Settings.Default.AllPeople = new ObservableCollection<Person> 
        { 
            new Person() { FirstName = "bob" },
            new Person() { FirstName = "sue" },
            new Person() { FirstName = "bill" }
        };
        Properties.Settings.Default.Save();
    }
    else
    {
        MessageBox.Show(Properties.Settings.Default.AllPeople.People.Count.ToString());
    }
}
3 голосов
/ 06 марта 2013

Если вы добавите ObservableCollection<People> к своему собственному коду, но укажете пространство имен «Свойства», вы можете внести это изменение без изменения настроек. Дизайн.cs:

namespace MyApplication.Properties
{  
    public sealed partial class Settings
    {
        [global::System.Configuration.UserScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public ObservableCollection<Person> AllPeople
        {
            get
            {
                return ((ObservableCollection<Person>)(this["AllPeople"]));
            }
            set
            {
                this["AllPeople"] = value;
            }
        }
    }
}

Обратите внимание, я изменил доступность класса Settings на public. (мне, вероятно, не нужно было этого делать).

Единственный недостаток, который я увидел во всем этом решении / ответе, заключается в том, что вы больше не можете вносить изменения в параметры конфигурации приложения с помощью диалога «Проект» -> «Свойства». В этом случае серьезно испортит ваши новые настройки, преобразовав настройки в строку и исказив ваши XML-теги.

Поскольку я хотел использовать один общесистемный файл конфигурации вместо пользовательского файла, я также изменил global::System.Configuration.UserScopedSettingAttribute()] на [global::System.Configuration.ApplicationScopedSetting()]. Я оставил в классе set accesser, но я знаю, что на самом деле это не спасает.

Спасибо за ответ! Это делает мой код намного чище и проще в управлении.

...