【问题标题】:Saving setting to the App.Config, using an ICommand or not?是否使用 ICommand 将设置保存到 App.Config?
【发布时间】:2012-03-21 09:10:58
【问题描述】:

我在玩 MVVM,了解模式中涉及的内容。我正在编写的第一个应用程序是一个非常小的应用程序,它基本上显示来自 App.Config 的 2 个设置。

我的目标是在单击按钮时能够写入此 app.config。

我的问题在于我不确切知道如何连接一个命令来委派这项工作,或者这是否是要走的路。

我的 App.config 非常简单:

 <configuration>
  <appSettings>
    <add key="duration" value="100" />
    <add key="operators" value="10" />
  </appSettings>
</configuration>

模型如下:

    get
    {
        // try to parse the setting from the configuration file
        // if it fails return the default setting 0
        int durationSetting = 0;                
        Int32.TryParse(ConfigurationManager.AppSettings["duration"], out durationSetting);

        return durationSetting;
    }
    set
    {                
        var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        config.AppSettings.Settings.Remove("duration");
        config.AppSettings.Settings.Add("duration", Convert.ToString(value));
        ConfigurationManager.RefreshSection("appSettings");
        config.Save();       
    }
}

那么,模型负责实际的数据访问,这就是我们想要的,对吧?

此外,我有一个 ViewModel(ViewModelBase 实现了 INotifyPropertyChanged):

public class SettingsViewModel : ViewModelBase 
{
    private Settings Settings { get; set; }

    private SaveCommand saveCommand = new SaveCommand();

    public ICommand SaveCommand
    {
        get
        {
            return saveCommand;
        }
    }

    public SettingsViewModel(Settings settings)
    {
        if (settings == null)
            throw new ArgumentNullException("Settings", "Settings cannot be null");
        Settings = settings;
    }

    public int Duration
    {
        get { return Settings.Duration; }
        set
        {
            if (Settings.Duration != value)
            {
                Settings.Duration = value;
                RaisePropertyChanged("Duration");
            }
        }
    }

视图是一个 xaml 用户控件,实例化如下:

public partial class MainWindow : Window
{
    public SettingsViewModel SettingsViewModel { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;

        Settings settings = new Settings();

        SettingsViewModel = new SettingsViewModel(settings);
    }
}

最后有一个实现 ICommand 的 SaveCommand,此时它基本上是空的。我已将命令连接到视图中的按钮。

但基本上,现在呢?处理保存值的最佳方法是什么? 我正在研究的示例是否过于做作?

【问题讨论】:

    标签: c# wpf mvvm command


    【解决方案1】:

    我建议使用非常有用的MVVM Light toolkit

    基本上,您将公开一个返回RelayCommand 实例的ICommand 公共属性:

    private RelayCommand myCommand;
    
    public ICommand MyCommand
    {
        get
        {
            return this.myCommand;
        }
    }
    
    ...
    
    // in constructor of the view model:
    this.myCommand = new RelayCommand(this.MyCommandImplementation);
    
    ...
    
    private void MyCommandImplementation()
    {
        // Save your parameters here from your model
    }
    

    您的代码中有些奇怪的是,您实际上已经将设置保存在名为Duration 的公共属性的设置器中。 您可以做的(防止每次修改属性时保存)只是在 ViewModel 中使用私有变量:

    private int duration;
    public int Duration
    {
        get { return this.duration; }
        set
        {
            if (this.duration != value)
            {
                this.duration = value;
                RaisePropertyChanged("Duration");
            }
        }
    }
    

    因此,当您修改绑定到 Duration 属性的 UI 字段时,您只会更新私有 duration 字段。因此,您只需将其保存到 MyCommandImplementation 方法中的 app.config 文件中。

    private void MyCommandImplementation()
    {
        this.Settings.Duration = this.Duration;
    }
    

    还请注意,您的Settings 管理有点复杂(您删除然后再次添加设置,为什么?)。 最后一件事:在您的视图中,您当前正在使用视图本身作为数据上下文。您必须指定您的 ViewModel:

    this.SettingsViewModel = new SettingsViewModel(settings);
    this.DataContext = this.SettingsViewModel;
    

    另外,我认为实例化模型不是视图的作用。我会改为从 ViewModel 实例化 Settings

    【讨论】:

    • 是的,由于保存行为,我想知道在这种情况下该命令是否不必要 cq 我的示例过于做作。设置是这样完成的,因为好像没有编辑方法。
    • @fuaaark 好吧,由您来选择您真正想要的。如果您的目标是“在单击按钮时能够写入此 app.config”,那么您将需要一个按钮和一个 ICommand。如果你不需要按钮,那么只需保存到属性设置器中的 app.config 文件,你就不需要ICommand
    • 我将使用命令来实现它,以学习东西:) 但我可能应该考虑一些 SaveSettings() 方法并从命令中调用它,以免污染命令数据访问逻辑。对吗?
    • @fuaaark 在上面的代码中,您可以看到只有一个私有字段和一个公开命令的公共属性。所有逻辑都在MyCommandImplementation 方法中实现。用这种方法编写所有的保存逻辑是完全可以的。从MyCommandImplementation() 调用SaveSettings() 方法并没有太大帮助,您可以直接在MyCommandImplementation 中编写逻辑。
    【解决方案2】:

    您需要做的就是在一个类中实现 ICommand 接口并将 SaveCommand 属性设置为该类的一个实例。您可以使用一些第三方命令类,例如 prism 库的 DelegateCommand 或 RelayCommand。 ICommand 的示例实现请参考以下网页; http://weblogs.asp.net/fredriknormen/archive/2010/01/03/silverlight-4-make-commanding-use-lesser-code.aspx

    然后将要使用的动作注册在命令中;

    this.SaveCommand= new SaveCommand((o) =>
            {
                //change the model
            });
    

    【讨论】:

    • 我在一个名为“SaveCommand”的类中描述了我的问题状态。
    猜你喜欢
    • 2011-12-23
    • 2017-09-14
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    相关资源
    最近更新 更多