c# - 在WPF应用程序中保存用户设置的方法?

Gre*_*reg 69 .net c# wpf settings

您建议在WPF窗口(桌面)应用程序中保留用户设置的方法是什么?请注意,该想法是用户可以在运行时更改其设置,然后可以关闭应用程序,然后在稍后启动应用程序时,应用程序将使用当前设置.有效地,它看起来好像应用程序设置不会改变.

Q1 - 数据库还是其他方法?我确实有一个我将使用的sqlite数据库,因此使用数据库中的表将与任何方法一样好吗?

Q2 - 如果数据库:什么数据库表设计?与一个可能有不同的数据类型的列一个表(例如string,long,DateTime等),或者只是一个用于在您拥有序列化和反序列化值,该值的字符串表?我想第一个会更容易,如果设置不多,开销就不多了?

Q3 - 可以使用应用程序设置吗?如果是这样,是否需要在此处启用持久性的特殊任务?在这种情况下,在应用程序设置设计器中使用"默认"值会发生什么?默认会覆盖运行应用程序之间保存的所有设置吗?(或者你需要不使用默认值)

akj*_*shi 68

您可以使用应用程序设置,考虑到读取和写入设置所花费的时间(特别是如果您使用Web服务),使用数据库不是最佳选择.

以下是一些解释如何实现这一点并在WPF中使用它们的链接 -

WPF中的用户设置

快速WPF提示:如何绑定到WPF应用程序资源和设置?

WPF的可配置窗口


Gle*_*den 12

您可以Strings在XML中存储XML格式的设置信息Settings.Default.创建一些类来存储配置数据并确保它们是[Serializable].然后,使用以下帮助程序,您可以将这些对象的实例 - 或List<T>(或数组T[]等)序列化为String.将这些不同的字符串中的每一个存储Settings.Default在WPF应用程序的各自插槽中Settings.

要在下次应用程序启动时恢复对象,请读取Settings感兴趣的字符串和Deserialize预期的类型T(此时必须明确指定为类型参数Deserialize<T>).

public static String Serialize<T>(T t)
{
    using (StringWriter sw = new StringWriter())
    using (XmlWriter xw = XmlWriter.Create(sw))
    {
        new XmlSerializer(typeof(T)).Serialize(xw, t);
        return sw.GetStringBuilder().ToString();
    }
}

public static T Deserialize<T>(String s_xml)
{
    using (XmlReader xw = XmlReader.Create(new StringReader(s_xml)))
        return (T)new XmlSerializer(typeof(T)).Deserialize(xw);
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*Mat 10

我也更喜欢序列化文件.XML文件几乎适合所有要求.您可以使用ApplicationSettings内置版本,但这些内容有一些限制和定义但(对我来说)存储的非常奇怪的行为.我经常使用它们并且它们起作用.但是如果你想完全控制它们存储的方式和位置,我会使用另一种方法.

  1. 使用所有设置在某处创建课程.我把它命名了MySettings
  2. 实现保存和读取持久性
  3. 在您的应用程序代码中使用它们

好处:

  • 非常简单的方法.
  • 一类设置.加载.保存.
  • 您的所有设置都是类型安全的.
  • 您可以根据需要简化或扩展逻辑(版本控制,每个用户的许多配置文件等)
  • 它在任何情况下都很好用(数据库,WinForms,WPF,服务等......)
  • 您可以定义XML文件的存储位置.
  • 您可以通过代码或手动找到它们并对其进行操作
  • 它适用于我能想象的任何部署方法.

缺点: - 您必须考虑存储设置文件的位置.(但你可以使用你的安装文件夹)

这是一个简单的例子(未经测试) -

public class MySettings
{
    public string Setting1 { get; set; }
    public List<string> Setting2 { get; set; }

    public void Save(string filename)
    {
        using (StreamWriter sw = new StreamWriter(filename))
        {
            XmlSerializer xmls = new XmlSerializer(typeof(MySettings));
            xmls.Serialize(sw, this);
        }
    }
    public MySettings Read(string filename)
    {
        using (StreamReader sw = new StreamReader(filename))
        {
            XmlSerializer xmls = new XmlSerializer(typeof(MySettings));
            return xmls.Deserialize(sw) as MySettings;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用它.只需检查用户设置是否存在,就可以加载默认值或使用用户设置覆盖默认值:

public class MyApplicationLogic
{
    public const string UserSettingsFilename = "settings.xml";
    public string _DefaultSettingspath = 
        Assembly.GetEntryAssembly().Location + 
        "\\Settings\\" + UserSettingsFilename;

    public string _UserSettingsPath = 
        Assembly.GetEntryAssembly().Location + 
        "\\Settings\\UserSettings\\" + 
        UserSettingsFilename;

    public MyApplicationLogic()
    {
        // if default settings exist
        if (File.Exists(_UserSettingsPath))
            this.Settings = Settings.Read(_UserSettingsPath);
        else
            this.Settings = Settings.Read(_DefaultSettingspath);
    }
    public MySettings Settings { get; private set; }

    public void SaveUserSettings()
    {
        Settings.Save(_UserSettingsPath);
    }
}
Run Code Online (Sandbox Code Playgroud)

也许有人会受到这种方法的启发.这就是我多年来一直这样做的原因,我很满意.

  • 完全同意"存储它们的非常奇怪的行为",我正是因为这个而正在使用你的方法.+1. (2认同)

Jef*_*eff 6

长期运行这个问题的最典型方法是:隔离存储.

将控件状态序列化为XML或其他格式(如果使用WPF保存依赖项属性,则特别容易),然后将文件保存到用户的独立存储中.

如果您确实想要进入应用程序设置路线,我自己尝试了类似的东西......虽然下面的方法可以很容易地适应使用隔离存储:

class SettingsManager
{
    public static void LoadSettings(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        EnsureProperties(sender, savedElements);
        foreach (FrameworkElement element in savedElements.Keys)
        {
            try
            {
                element.SetValue(savedElements[element], Properties.Settings.Default[sender.Name + "." + element.Name]);
            }
            catch (Exception ex) { }
        }
    }

    public static void SaveSettings(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        EnsureProperties(sender, savedElements);
        foreach (FrameworkElement element in savedElements.Keys)
        {
            Properties.Settings.Default[sender.Name + "." + element.Name] = element.GetValue(savedElements[element]);
        }
        Properties.Settings.Default.Save();
    }

    public static void EnsureProperties(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        foreach (FrameworkElement element in savedElements.Keys)
        {
            bool hasProperty =
                Properties.Settings.Default.Properties[sender.Name + "." + element.Name] != null;

            if (!hasProperty)
            {
                SettingsAttributeDictionary attributes = new SettingsAttributeDictionary();
                UserScopedSettingAttribute attribute = new UserScopedSettingAttribute();
                attributes.Add(attribute.GetType(), attribute);

                SettingsProperty property = new SettingsProperty(sender.Name + "." + element.Name,
                    savedElements[element].DefaultMetadata.DefaultValue.GetType(), Properties.Settings.Default.Providers["LocalFileSettingsProvider"], false, null, SettingsSerializeAs.String, attributes, true, true);
                Properties.Settings.Default.Properties.Add(property);
            }
        }
        Properties.Settings.Default.Reload();
    }
}
Run Code Online (Sandbox Code Playgroud)

.....和....

  Dictionary<FrameworkElement, DependencyProperty> savedElements = new Dictionary<FrameworkElement, DependencyProperty>();

public Window_Load(object sender, EventArgs e) {
           savedElements.Add(firstNameText, TextBox.TextProperty);
                savedElements.Add(lastNameText, TextBox.TextProperty);

            SettingsManager.LoadSettings(this, savedElements);
}

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            SettingsManager.SaveSettings(this, savedElements);
        }
Run Code Online (Sandbox Code Playgroud)


aja*_*hiz 5

除了数据库,您还可以使用以下选项来保存用户相关设置

  1. 下注册 HKEY_CURRENT_USER

  2. 在文件AppData夹中的文件中

  3. Settings在 WPF 中使用文件并将其范围设置为用户

  • 建议 1 是应用程序降低 Windows 速度的原因,最好不要在文件 IMO 中用更好的东西填充注册表项。 (2认同)