【问题标题】:Best practices for storing UI settings?存储 UI 设置的最佳实践?
【发布时间】:2010-09-19 19:08:58
【问题描述】:

我们目前正在计划一个更大的 WPF LoB 应用程序,我想知道其他人认为存储大量 UI 设置的最佳做法是什么,例如

  • 扩展国家
  • 菜单订单
  • 尺寸属性
  • 等等……

我不喜欢使用提供的 SettingsProvider(即 App.config 文件)存储数十个值的想法,尽管它可以用于使用自定义 SettingsProvider 将其存储在嵌入式数据库中。 能够使用某种数据绑定也是一个问题。 有没有人有同样的问题?

您如何存储大量 ui 用户设置?

【问题讨论】:

    标签: c# wpf settings appsettings


    【解决方案1】:

    我们将首选项文件存储在这里:

    Environment.SpecialFolder.ApplicationData
    

    将其存储为 xml“首选项”文件,这样在损坏时访问和更改并不难。

    到目前为止,这对我们来说比注册表效果要好得多,如果有任何东西损坏或需要重置,它会更干净、更容易清除。

    【讨论】:

      【解决方案2】:

      存储 UI 设置的更快方法是使用 Properties.Settings.Default 系统。它的好处是使用 WPF 绑定到值。 Example here。设置会自动更新和加载。

      <Window ...
          xmlns:p="clr-namespace:UserSettings.Properties"
          Height="{Binding Source={x:Static p:Settings.Default}, Path=Height, Mode=TwoWay}" 
          Width="{Binding Source={x:Static p:Settings.Default}, Path=Width, Mode=TwoWay}" 
          Left="{Binding Source={x:Static p:Settings.Default}, Path=Left, Mode=TwoWay}" 
          Top="{Binding Source={x:Static p:Settings.Default}, Path=Top, Mode=TwoWay}">
      
      ...
      protected override void OnClosing(System.ComponentModel.CancelEventArgs e) 
      { 
          Settings.Default.Save(); 
          base.OnClosing(e); 
      }
      

      问题在于,如果您的应用程序很大,它很快就会变得一团糟。

      另一种解决方案(此处有人提出)是使用 ApplicationData 路径将您自己的首选项存储到 XML 中。在那里,您可以构建自己的设置类并使用 XML 序列化程序来持久化它。这种方法使您能够从版本迁移到版本。虽然功能更强大,但此方法需要更多代码。

      【讨论】:

        【解决方案3】:

        深入研究 aogan 的答案并将其与 decasteljau 的答案和他引用的博客文章相结合,这是一个示例,填补了我不清楚的一些空白。

        xaml 文件:

        <Window ...
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:p="clr-namespace:MyApp"
            Height="{Binding Source={x:Static p:MyAppSettings.Default}, Path=MainWndHeight, Mode=TwoWay}"
            Width="{Binding Source={x:Static p:MyAppSettings.Default}, Path=MainWndWidth, Mode=TwoWay}"
            Left="{Binding Source={x:Static p:MyAppSettings.Default}, Path=MainWndLeft, Mode=TwoWay}"
            Top="{Binding Source={x:Static p:MyAppSettings.Default}, Path=MainWndTop, Mode=TwoWay}"
            ...
        

        还有源文件:

        namespace MyApp
        {
            class MainWindow ....
            {
                ...
        
                protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
                {
                    MyAppSettings.Default.Save();
                    base.OnClosing(e);
                }
            }
        
            public sealed class MyAppSettings : System.Configuration.ApplicationSettingsBase
            {
                private static MyAppSettings defaultInstance = ((MyAppSettings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new MyAppSettings())));
                public static MyAppSettings Default
                {
                    get { return defaultInstance; }
                }
        
                [System.Configuration.UserScopedSettingAttribute()]
                [System.Configuration.DefaultSettingValueAttribute("540")]
                public int MainWndHeight
                {
                    get { return (int)this["MainWndHeight"]; }
                    set { this["MainWndHeight"] = value; }
                }
        
                [System.Configuration.UserScopedSettingAttribute()]
                [System.Configuration.DefaultSettingValueAttribute("790")]
                public int MainWndWidth
                {
                    get { return (int)this["MainWndWidth"]; }
                    set { this["MainWndWidth"] = value; }
                }
        
                [System.Configuration.UserScopedSettingAttribute()]
                [System.Configuration.DefaultSettingValueAttribute("300")]
                public int MainWndTop
                {
                    get { return (int)this["MainWndTop"]; }
                    set { this["MainWndTop"] = value; }
                }
        
                [System.Configuration.UserScopedSettingAttribute()]
                [System.Configuration.DefaultSettingValueAttribute("300")]
                public int MainWndLeft
                {
                    get { return (int)this["MainWndLeft"]; }
                    set { this["MainWndLeft"] = value; }
                }
            }
        }
        

        【讨论】:

          【解决方案4】:

          我们将所有内容存储在Isolation Storage 中(我们使用 ClickOnce 运行)。我们有一些要序列化的对象 (XmlSerializer)。

          【讨论】:

            【解决方案5】:

            似乎由于某种原因正在失去人气;但注册表一直是此类设置的合适位置。

            【讨论】:

            • 注册表绝对不再是正确的地方。注册表损坏,不当使用可能导致安全问题,并可能违反 LUA/UAC 原则。 secureapps.blogspot.com/2006/10/…
            • 好吧,UI 设置几乎与安全无关,是吗?
            • 它们很容易被破坏并且容易出错。我宁愿让普通用户轻松访问它们。
            • 别管安全相关,注册表写入经常会产生 LUA/UAC 问题,注册表很容易损坏等等。Microsoft 自己最近建议不要这样做,并支持 IsolatedStorage 或 Environment.SpecialFolder.ApplicationData这些原因。
            【解决方案6】:

            我们使用自定义 SettingsProvider 将配置信息存储在应用程序数据库的表中。如果您已经在使用数据库,这是一个很好的解决方案。

            【讨论】:

              【解决方案7】:

              在 Chris Sells 和 Ian Griffiths 编写的 Programming WPF 中说

              WPF 应用程序的首选设置机制是 .NET 和 VS 提供的一种:System.Configuration 命名空间中带有内置设计器的 ApplicationSettingBase 类。

              【讨论】:

              • 不幸的是,设置设计器(在 vs2008 中)将您在设计器中设置的任何设置具体化为 settings.Designer.vb 中的 DefaultSettingValueAttribute 条目。似乎没有办法关闭它。如果您手动编辑配置文件,那么下次您在设置设计器中进行编辑时,它将重新同步。这太糟糕了。这可能会导致应用程序使用硬编码的默认值(有些隐藏)进行部署,如果 app.config 设置丢失,它将采取行动。 tinyurl.com/3xyzz66
              猜你喜欢
              • 2012-06-26
              • 2012-01-14
              • 2012-05-10
              • 1970-01-01
              • 2010-10-05
              • 1970-01-01
              • 2019-11-27
              • 1970-01-01
              相关资源
              最近更新 更多