WPF应用程序设置-重置单个属性

本文关键字:单个 属性 -重 应用程序 设置 WPF | 更新日期: 2024-09-20 22:32:19

有一种方法可以使用Settings.Default.Reset() 重置应用程序设置

有没有办法只重置一个属性?类似的东西

Settings.Default.Properties["MyPropertyName"].Reset();

WPF应用程序设置-重置单个属性

您可以使用Settings.Default.Properties["MyProperty"].DefaultValue来获取属性的默认值,并将属性值设置为该值。

需要在Deserialized(顺序事项)的组合中设置PropertyValue

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;
    }
}

读取时找到解决方案。NET源代码:

Settings.Default.PropertyValues["MyPropertyName"].SerializedValue = Settings.Default.Properties["MyPropertyName"].DefaultValue;
Settings.Default.PropertyValues["MyPropertyName"].Deserialized = false;

在我的情况下(.NET Framework 4.6.1,设置为System.Drawing.Color),我还必须重新分配Settings.Default中的值,否则更改似乎被忽略了:

var propertyValue = Settings.Default.PropertyValues["myPropertyName"];
propertyValue.PropertyValue = propertyValue.Property.DefaultValue;
propertyValue.Deserialized = false;
Settings.Default["myPropertyName"] = propertyValue.PropertyValue;

我使用以下代码重置程序中的设置。它利用反射,允许您直接传递属性,而不是手动写出属性名称。它可以像ResetToDefaultValue(TestSettings.Default, x => x.TextFieldStuff); 一样使用

这样做的好处是,并非所有设置都在Settings中,但有些设置可能存储在不同的设置文件中。

//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;
}

或者,如果您使用的是C#7.1或更高版本,则可以使用功能匹配。

//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));
}

当我查看@dalleria和@nikita的答案时,我遇到了以下问题当我尝试获取DefaultValue(SettingsProperty)、PropertyValue(SettingsPropertyValue)或任何其他相同类型值的深度副本时,PropertyValue(SettingsPropertyValue)意外默认。

这是我的一个深度复制函数的简短实现,它是一个类的一部分,所以我很抱歉没有将它重构为扩展或工具方法。

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;
}

然后,您可以使用以下行重置ApplicationSettings/SettingsBase实例的单个属性:

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;
}