2

I have a WPF GUI that allows the user to open up an options menu. The option menu opens in a new window and is filled with check boxes. When the user presses the "ok" button the window closes. However, it doesn't remember what check boxes were checked when it is opened back up. How do I make sure the program is able to remember what boxes were checked and which ones weren't?

Just to specify: I only need to remember which boxes are checked during the run of the program. The program does not need to remember after the entire program has been exited.

Thanks!

Here is my code under the main window Window1.XAML.CS:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CartToolsPrototype1
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        //Exit
        private void Exit_Click(object sender, RoutedEventArgs e)
        {
            System.Environment.Exit(0);
        }

        //Options
        private void Options_Click(object sender, RoutedEventArgs e)
        {
            var newWindow = new Options();
            newWindow.Show();
        }
    }
}

Here is my code under the child Window Options.XAML.CS. This is based off of the first answer. I've read through the link you posted and it makes sense. I have conditions in my settings file that I change when the user checks my check boxes. I then have a condition that determines whether the box is checked based on the settings file, but it doesn't seem to reflect any change...

public partial class Options_Window : Window
    {
        public Options_Window()
        {
            InitializeComponent();

            //Checkbox1
            if (Properties.Settings.Default.OptionsBox1 == true)
                checkBox1.IsChecked = true;
            else
                checkBox1.IsChecked = false;
        }

        //Close Window
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        //Ask before downloading... - CHECKED
        private void checkBox1_Checked(object sender, RoutedEventArgs e)
        {
            Properties.Settings.Default.OptionsBox1 = true;
        }

        //Ask before downloading... - UNCHECKED
        private void checkBox1_Unchecked(object sender, RoutedEventArgs e)
        {
            Properties.Settings.Default.OptionsBox1 = false;
        }
Eric after dark
  • 1,768
  • 4
  • 31
  • 79
  • Have you considered binding the checkboxes to bool properties in a ViewModel? If you mean the main window closes, you'd need to persist those states in some way; perhaps an xml file. –  Jul 10 '13 at 18:06
  • 1
    Just to be clear, are you trying to keep this persistent even after you restart your entire program? If that's the case, I'd save it to an XML file in your APPDATA folder. – Alex Jul 10 '13 at 18:08
  • Just during the run of the program. If the user opens up the options window again I would like to have the same check boxes checked off. – Eric after dark Jul 10 '13 at 18:22
  • 1
    You can also use settings to save data during the run of the application. – dsfgsho Jul 10 '13 at 18:25
  • And how exactly would I do that? – Eric after dark Jul 10 '13 at 18:35
  • Just saying something implements INotifyPropertyChanged doesn't actually implement it. Did you forget to have a PropertyChanged event handler and raise it during the IsSettingSet setter method? [MSDN](http://msdn.microsoft.com/en-us/library/ms743695.aspx) – Mike Cofoed Jul 12 '13 at 19:22

3 Answers3

6

You can use Settings to share data between different Windows/Controls and even save application data when closing/starting an application.

The .NET Framework allows you to create and access values that are persisted between application execution sessions. These values are called settings. Settings can represent user preferences, or valuable information the application needs to use. For example, you might create a series of settings that store user preferences for the color scheme of an application. Or you might store the connection string that specifies a database that your application uses. Settings allow you to both persist information that is critical to the application outside of the code, and to create profiles that store the preferences of individual users.

You can save a Setting in any Window:

Properties.Settings.Default.mySetting = true;
Properties.Settings.Default.Save();

You can read/use a setting in any Window:

this.Property = Properties.Settings.Default.mySetting;
dsfgsho
  • 2,731
  • 2
  • 22
  • 39
  • Hey, this makes a lot of sense, but my program doesn't seem to be noticing any change in the settings.settings file. I've edited my post based on your solution, please take a look, I think I'm close. – Eric after dark Jul 19 '13 at 14:24
  • Don't forget the `Properties.Settings.Default.Save();` – dsfgsho Jul 19 '13 at 14:26
  • Where exactly should it go? I was putting it right before `this.close();` – Eric after dark Jul 19 '13 at 14:27
  • That's fine. Have you defined your setting scope (third column in properties -> settings) as User? – dsfgsho Jul 19 '13 at 14:33
  • Yes, all settings are of user scope. – Eric after dark Jul 19 '13 at 14:34
  • Mmm, right before closing should be fine. What happens if you save immediately? – dsfgsho Jul 19 '13 at 14:44
  • I deleted the save after `this.close();` and put it right after `InitializeComponent();`, still the same, it doesn't appear to affect anything. – Eric after dark Jul 19 '13 at 14:46
  • The `Save()` method should be in the same Window either before the Close method, but personally I always call save in the same method where I set the setting, like in my example. Also, if you put it right after `InitializeComponent();`, it cannot save anything, since you are not changing any setting until you hit the checkbox? – dsfgsho Jul 19 '13 at 14:56
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/33778/discussion-between-eric-after-dark-and-stevenhouben) – Eric after dark Jul 19 '13 at 14:59
1

First we need a settings object, that stores our properties. Remember to properly implement INotifyPropertyChanged

class MySettings : INotifyPropertyChanged
{
    public bool IsSettingSet {get;set;}
}

then in our settings window, just use bindings to bind the view controls to your Settings object.

<Window 
    x:Class="SettingsWindow"
    ...>
    <CheckBox IsChecked="{Binding IsSettingSet}"/>
</Window>

and finally where you actually open the window, you need to assign your settings object to the DataContext of your settings window.

class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }
    void OpenSettingsWindow()
    {
        var dlg = new SettingsWindow();
        dlg.DataContext = mGlobalSettings;
        dlg.ShowDialog();
    }

    MySettings mGlobalSettings = new MySettings();
}

now everytime you open the window, your settings will be the same like they were last time. As long as you don't close the application.

dowhilefor
  • 10,971
  • 3
  • 28
  • 45
  • I have implemented the code, the only build error I am getting has to do with the settings windows' .XAML window. It says that `Checked="{Binding IsSettingSet}" is not valid. '{Binding IsSettingSet}" is not a valid event handler method name. Only instance methods on the generated or code-behind class are valid.` – Eric after dark Jul 12 '13 at 18:19
  • `Checked` is an event. The binding should be done with the `IsChecked` property instead. I've edited @dowhilefor's code example to be a bit more complete. – Steve Jul 12 '13 at 18:22
  • In my opinion, this is the best answer to the question and should be accepted. – Steve Jul 12 '13 at 18:31
  • Yes i'm sorry, that was a typo. – dowhilefor Jul 12 '13 at 21:05
0

If it's just during runtime, then it's pretty easy. You could use a static class:

public static class MyState
{
    public static bool IsChecked1 { get; set; }
}

Or a singleton instance of a class:

public class MyState   
{
   private static MyState _instance = new MyState();

   public static MyState Instance 
   {
      get { return _instance; }
   }

   private MyState() {}

   public bool IsChecked1 { get; set; }

}

When the window loads, get the state from the properties of MyClass. When the window is closing, set the properties of MyClass.

In Options.xaml.cs:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    CheckBox1.IsChecked = MyState.IsChecked1;
}

private void Window_Closed(object sender, EventArgs e)
{
    MyState.IsChecked1 = CheckBox1.IsChecked;
}
RQDQ
  • 15,461
  • 2
  • 32
  • 59
  • How would I make sure that code is dedicated to my Options.xaml window? It doesn't really seem like there's anything in that code that would call to the window. – Eric after dark Jul 10 '13 at 19:11
  • This of it the other way around - your Options.xaml window would reference the values in MyState when it loads and closes. – RQDQ Jul 10 '13 at 20:07
  • Okay, I've implemented the code into my Options.xaml.cs window and tried to make sure that I accounted for all of my check boxes. However, the compiler says that "A get or set accessor expected". Do I need to add something before get and set? I've posted my code, thanks. – Eric after dark Jul 10 '13 at 20:50
  • You're very close... You're using the second approach that I recommended. Just do MyState.Instance.IsChecked1 – RQDQ Jul 11 '13 at 02:58
  • I added `MyState.Instance` to every spot that I thought it should go, but anywhere I put it I received an error. I have updated the code and written down the errors. There must be something I'm missing. Thanks. – Eric after dark Jul 12 '13 at 12:20
  • Apologies - I had misspelled _instance and left out the get clause in the Instance property. I've fixed it in my answer. – RQDQ Jul 12 '13 at 12:36
  • Alright, I've added the get clause and updated my code. I'm still getting errors that I don't really have a clue about. They're written up there. Thanks for bearing with me. – Eric after dark Jul 12 '13 at 12:46
  • Add the 's' to _intance where it is declared. – RQDQ Jul 12 '13 at 12:47
  • Do you mean in the `private static MyState _instance = new MyState();` line? – Eric after dark Jul 12 '13 at 12:59
  • @RQDQ why don't use data binding? The usage of Loaded and Closed is so WinForms. – dowhilefor Jul 12 '13 at 13:40
  • @RQDQ - in my solutions I tend to use MVVM (with binding of course). I'm trying to answer based on the OP's perceived experience level. – RQDQ Jul 12 '13 at 14:04