TransWikia.com

Как программно добавить и прочитать новое свойство в конфигурацию пользователя?

Stack Overflow на русском Asked by XelaNimed on December 7, 2021

Стоит задача сохранять и устанавливать размеры окон WinFroms приложения при открытии и закрытии для каждого пользователя программы на локальном компьютере. Для этого в базовый класс форм было добавлено пара методов, которые вызываются при открытии и закрытии формы:

// вызывается при открытии формы
private void _setFormSize()
{
    Type t = GetType();
    string propName = $"{t.Name}_FormSize";
    try
    {
        // никогда не находит и выбрасывает исключение
        // System.Configuration.SettingsPropertyNotFoundException
        // "The settings property 'FormMain_FormSize' was not found."
        var formSize = (Size)Properties.Settings.Default[propName];
        if (formSize.Width > 0 && formSize.Height > 0)
        {
            Size = formSize;
        }
    }
    catch (Exception ex)
    {
        var baseProp = Properties.Settings.Default.Properties["FormSizeBase"];
        var prop = new SettingsProperty(propName)
        {
            Name = propName,
            IsReadOnly = false,
            PropertyType = typeof(Size),
            DefaultValue = Size.Empty,
            SerializeAs = SettingsSerializeAs.String,
            // читаю вручную добавленое свойства для получения Provider :(
            // Как создать Provider программно?
            Provider = baseProp.Provider
        };
        // этого аттрибута хватит? Или нужно ещё что-то добавить?
        prop.Attributes.Add(typeof(UserScopedSettingAttribute), new UserScopedSettingAttribute());
        
        Properties.Settings.Default.Properties.Add(prop);
        Properties.Settings.Default.Reload();
        Properties.Settings.Default[propName] = Size;
        Properties.Settings.Default.Save();
    }
}
// вызывется при закрытии формы и корректно сохраняет значение в
// %localappdata%CompanyApp.exe_Url_1blablabla.0.0.1user.config
private void _saveFormSize()
{
    Type t = GetType();
    string propName = $"{t.Name}_FormSize";
    Properties.Settings.Default[propName] = Size;
    Properties.Settings.Default.Save();
}

Так выглядит FormSizeBase в конструкторе:

Project Properties - Settings Tab

Проблема в том, что я не могу прочитать свойство, т.е. строка var formSize = (Size)Properties.Settings.Default[propName]; никогда не находит свойство, хотя в файле %localappdata%CompanyApp.exe_Url_1blablabla.0.0.1user.config оно присутствует:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <userSettings>
        <AppNamespace.Properties.Settings>
            <setting name="FormSizeBase" serializeAs="String">
                <value>563, 489</value>
            </setting>
            <setting name="FormMain_FormSize" serializeAs="String">
                <value>347, 284</value>
            </setting>
        </AppNamespace.Properties.Settings>
    </userSettings>
</configuration>

Что я делаю не правильно? Как прочитать конфигурацию из user.config?


P.S.: propName определяется правильно:

propertyName in debugger

One Answer

Вы не учитываете маленькую деталь. Settings API - это очень топорная вещь, рассчитанная на стандартный сценарий "конфигурировать набор свойств, заданный на этапе разработки". Если вы просто так добавляете что-то на лету в файл user.config, оно не будет волшебным образом считываться, так как программа тупо не знает о существовании этого нового свойства. Это значит, что свойство нужно создавать всегда, даже когда оно уже есть в файле. И делать это аккуратно, копируя существующее эталонное свойство и меняя в нем что нужно, а не заполнять все с нуля и гадать, хватит или не хватит. То есть код _setFormSize должен выглядеть как-то так:

Type t = GetType();
string propName = t.Name+"_FormSize";

var baseProp = Properties.Settings.Default.Properties["FormSizeBase"];
var prop = new SettingsProperty(baseProp)
{
    Name = propName
};

Properties.Settings.Default.Properties.Add(prop);
Properties.Settings.Default.Reload();
Size formSize = (Size)Properties.Settings.Default[propName];

if (formSize.Width > 0 && formSize.Height > 0)
{
    Size = formSize;
}
else
{
    Properties.Settings.Default[propName] = Size;
    Properties.Settings.Default.Save();
}

Answered by MSDN.WhiteKnight on December 7, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP