简体   繁体   中英

Saving setting to the App.Config, using an ICommand or not?

I'm playing around with MVVM, getting to know the stuff involved in the pattern. The first application I'm writing is a very small application which basically displays 2 settings from the App.Config.

My goal is to be able to write to this app.config when the button is clicked.

My problem lies in the fact I don't know exactly how to wire up a command to delegate this work to, or if this is even the way to go.

My App.config is very straight forward:

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

The model looks like:

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

So, the model is responsible for the actual data access, this is what we want, right?

Furthermore I have a ViewModel (ViewModelBase implements 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");
            }
        }
    }

The view is a xaml usercontrol, instantiated like this:

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

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

        Settings settings = new Settings();

        SettingsViewModel = new SettingsViewModel(settings);
    }
}

Lastly there's a SaveCommand which implements ICommand, which is basically empty at this point. I've hooked up the command to a button in the view.

But basically, now what? What's the best way to handle the saving of the values? Is the example I'm working on too contrived?

I would recommend using the very useful MVVM Light toolkit .

Basically, you will expose a ICommand public property that returns an instance of a RelayCommand :

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
}

Something strange in your code is that you actually already save your settings in the setter of the public property named Duration . What you could do instead (to prevent from saving each time the property is modified) is to simply use a private variable in your ViewModel:

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

So when you modify a UI field binded to your Duration property, you only update the private duration field. Thus you'll only save it to the app.config file in the MyCommandImplementation method.

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

Also note that your Settings management is a bit complicated (you remove then add again a settings, why?). Last thing: in your view, you're currently using the view itself as datacontext. You have to specify your ViewModel instead:

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

Also, I don't think it's the role of your view to instantiate your model. I would instantiate Settings from the ViewModel instead.

All you need to do is to implement ICommand interface in a class and set SaveCommand property to an instance of this class. You can either you some third party command classes, like DelegateCommand of prism library or RelayCommand. Refer to the following web page for a sample implementation of ICommand; http://weblogs.asp.net/fredriknormen/archive/2010/01/03/silverlight-4-make-commanding-use-lesser-code.aspx

then the actions to be employed shall be registered in the command;

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM