WPF application settings - resetting a single property
Asked Answered
V

6

12

There is a way to reset application settings with Settings.Default.Reset()

Is there a way to reset only one property? Something like

Settings.Default.Properties["MyPropertyName"].Reset();
Vincent answered 2/8, 2012 at 16:6 Comment(0)
V
5

Found solution when reading .NET source code:

Settings.Default.PropertyValues["MyPropertyName"].SerializedValue = Settings.Default.Properties["MyPropertyName"].DefaultValue;
Settings.Default.PropertyValues["MyPropertyName"].Deserialized = false;
Vincent answered 3/8, 2012 at 13:46 Comment(0)
G
14

You can use the Settings.Default.Properties["MyProperty"].DefaultValue to obtain the default value for the property, and set the property value to that.

Gothenburg answered 2/8, 2012 at 16:19 Comment(0)
K
6

It's the PropertyValue that's need to be set in combinaison of Deserialized (the order matter) :

public void ResetOneSetting(string propertyName)
{
    SettingsPropertyValue propertyToReset = Settings.Default.PropertyValues.OfType<SettingsPropertyValue>().FirstOrDefault(p => p.Name == propertyName);
    if (propertyToReset != null)
    {
        propertyToReset.PropertyValue = propertyToReset.Property.DefaultValue;
        propertyToReset.Deserialized = false;
    }
}
Knapweed answered 1/9, 2016 at 13:27 Comment(0)
V
5

Found solution when reading .NET source code:

Settings.Default.PropertyValues["MyPropertyName"].SerializedValue = Settings.Default.Properties["MyPropertyName"].DefaultValue;
Settings.Default.PropertyValues["MyPropertyName"].Deserialized = false;
Vincent answered 3/8, 2012 at 13:46 Comment(0)
N
1

In my case (.NET Framework 4.6.1, with a System.Drawing.Color as setting), I also had to re-assign the value in Settings.Default, otherwise the change seemed to be ignored:

var propertyValue = Settings.Default.PropertyValues["myPropertyName"];

propertyValue.PropertyValue = propertyValue.Property.DefaultValue;
propertyValue.Deserialized = false;

Settings.Default["myPropertyName"] = propertyValue.PropertyValue;
Normand answered 21/7, 2018 at 22:31 Comment(0)
A
0

I use the following code to reset a setting in my program. It takes advantage of reflection and allows you to pass a property directly instead of you manually writing out a properties name. It can be used like ResetToDefaultValue(TestSettings.Default, x => x.TextFieldStuff);

The advantage of this is that it does not all your settings are in Settings but some might be stored in different settings files.

//Way to use
//ResetToDefaultValue(TestSettings.Default, x => x.TextFieldStuff);
private static void ResetToDefaultValue<T1, T2>(T1 settings, Expression<Func<T1, T2>> property, bool saveOnReset = true)
{
    if (IsSameOrSubclass(typeof(ApplicationSettingsBase), settings.GetType()))
    {
        ApplicationSettingsBase s = settings as ApplicationSettingsBase;
        if (s != null)
        {
            MemberInfo member = GetMemberInfo(property);
            if (!s.PropertyValues[member.Name].UsingDefaultValue)
            {
                s.PropertyValues[member.Name].PropertyValue = s.PropertyValues[member.Name].Property.DefaultValue;
                s.PropertyValues[member.Name].Deserialized = false;
                s[member.Name] = s.PropertyValues[member.Name].PropertyValue; //Triggers the property changed
                if (saveOnReset)
                {
                    s.Save();
                }
            }
        }
    }
}

//Way to use
//GetMemberInfo((TestSettings testSettings) => testSettings.TextFieldStuff);
private static MemberInfo GetMemberInfo<T1, T2>(Expression<Func<T1, T2>> expression)
{
    if (IsSameOrSubclass(typeof(MemberExpression), expression.Body.GetType()))
    {
        MemberExpression member = (MemberExpression)expression.Body;
        return member.Member;
    }

    throw new ArgumentException(@"Expression is not a member access", nameof(expression));
}

private static bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
    return potentialDescendant.IsSubclassOf(potentialBase)
           || potentialDescendant == potentialBase;
}

Or if you are using C# 7.1 or greater, you can use feature matching.

//Way to use
//ResetToDefaultValue(TestSettings.Default, x => x.TextFieldStuff);
private static void ResetToDefaultValue<T1, T2>(T1 settings, Expression<Func<T1, T2>> property, bool saveOnReset = true)
{
    //Requires C# >= 7.1
    if (settings is ApplicationSettingsBase s)
    {
        MemberInfo member = GetMemberInfo(property);
        if (!s.PropertyValues[member.Name].UsingDefaultValue)
        {
            s.PropertyValues[member.Name].PropertyValue = s.PropertyValues[member.Name].Property.DefaultValue;
            s.PropertyValues[member.Name].Deserialized = false;
            s[member.Name] = s.PropertyValues[member.Name].PropertyValue;
            if (saveOnReset)
            {
                s.Save();
            }
        }
    }
}

//Way to use
//GetMemberInfo((TestSettings testSettings) => testSettings.TextFieldStuff);
private static MemberInfo GetMemberInfo<T1, T2>(Expression<Func<T1, T2>> expression)
{
    //Requires C# >= 7.0
    if (expression.Body is MemberExpression member)
    {
        return member.Member;
    }

    throw new ArgumentException(@"Expression is not a member access", nameof(expression));
}
Aec answered 19/1, 2019 at 13:11 Comment(0)
B
0

While I checked out the answers from @dalleria and @nikita, I run into the problem that the PropertyValue (SettingsPropertyValue) got defaulted unexpectely when I tried to get a deep copy of DefaultValue (SettingsProperty) or PropertyValue (SettingsPropertyValue) or any other same typed value.

So here is my short implementation of a deep copy function that is part of a class, so I apologize for not refactoring it to a extension or tool method.

private SettingsPropertyValue settingsPropertyValue; // (ex. Settings.Default.PropertyValues["anyPropertyName"])

private SettingsProperty settingsProperty 
            => settingsPropertyValue.Property;

/// <summary>
/// Create a deep copy of <paramref name="value"/>.
/// </summary>
/// <param name="value">
/// Should be a deserialized value (ex. <see cref="SettingsPropertyValue.PropertyValue"/>) 
/// or a serialized value (ex. <see cref="SettingsProperty.DefaultValue"/>).
/// </param>
/// <param name="isDeserialized">Indicates whether <paramref name="value"/> is deserialized or serialized.</param>
private PropertyType copyValue<PropertyType>(object value, bool isDeserialized)
{
    var temporaryPropertyValue = settingsPropertyValue.PropertyValue;
    settingsPropertyValue.PropertyValue = value;

    if (isDeserialized)
        // We have to reassign, otherwise PropertyValue/SerializedValue of SettingsPropertyValue may be defaulted
        settingsPropertyValue.SerializedValue = settingsPropertyValue.SerializedValue; 

    settingsPropertyValue.Deserialized = false;
    var propertyValue = (PropertyType)settingsPropertyValue.PropertyValue;
    settingsPropertyValue.PropertyValue = temporaryPropertyValue;
    return propertyValue;
}

You can then reset a single property of an instance of ApplicationSettings/SettingsBase with these lines:

SettingsBase settings; // (ex. Settings.Default)

public void SetOriginalFromDefault()
{
    object defaultValue = settingsProperty.DefaultValue;
    defaultValue = copyValue(defaultValue, false);
    // We want to set the new value. It also triggers the INotifyPropertyChanged of settings, if the instance is from type ApplicationSettings
    settings[settingsProperty.Name] = defaultValue;
}
Boozy answered 23/9, 2019 at 10:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.