Click here to Skip to main content
15,881,793 members
Articles / Programming Languages / C#
Tip/Trick

Preferences Form Settings Dialog

Rate me:
Please Sign up or sign in to vote.
3.50/5 (3 votes)
27 Mar 2012CPOL 15.2K   307   4   2
How to build a standard preferences Form with tree node and content columns.

Introduction

A lot of desktop applications use a typical preferences dialog composed by a section node menu and the relative content selected on the right. 

Let's see how make it.

Using the code

First off, we start creating a form, an horizontal split container within a tree view and a TableLayoutPanel on the right columns.

Then we place two buttons, Save and Close on the bottom part of the TableLayoutPanel content.

This will look like this: 

Image 1

Typically, every single panel called by the menu section will have inside code for saving, validating and load settings at startup.

This is all granted by this interface

C#
interface IUserControlPrefPanel
{
    bool IsValid();
    void Save();
    void LoadSettings();
} 

Now we can start building up all custom panels needed using User Control and our interface IUserControlPrefPanel.

Once designed all the panels and implemented the three functions for each of these, the main form will have a code like this

C#
public Form1()
{
    InitializeComponent();
}

private UserControlPanelN0 userControlPanelN0 = new UserControlPanelN0();
private UserControlPanelN1 userControlPanelN1 = new UserControlPanelN1();

private UserControl mActivePanel;

private bool statusChanged = false;

private void Form1_Load(object sender, EventArgs e)
{
    userControlPanelN0.LoadSettings();
    userControlPanelN1.LoadSettings();

    userControlPanelN0.Visible = false;
    userControlPanelN1.Visible = false;

    treeViewMenu.SelectedNode = treeViewMenu.Nodes[0];

    AddEnableSaveOnChanges(userControlPanelN0);
    AddEnableSaveOnChanges(userControlPanelN1);
}

private void AddEnableSaveOnChanges(Control obj)
{
    foreach (Control control in obj.Controls)
    {
        control.TextChanged += EnableSave;

        // some events can occurs with your controls inside panel
        if (control.GetType() == typeof(CheckBox))
        {
            ((CheckBox)control).CheckedChanged += EnableSave;
        }

        if (control.GetType() == typeof(ListView))
        {
            ((ListView)control).SelectedIndexChanged += EnableSave;
        }

        // containers
        if (control.Controls.Count > 0)
            AddEnableSaveOnChanges(control);
    }
}

private void EnableSave(object sender, EventArgs e)
{
    statusChanged = true;
    this.buttonSave.Enabled = true;
}

private void treeViewMenu_AfterSelect(object sender, TreeViewEventArgs e)
{            
    UserControl newPanel = null;
    switch (e.Node.Index)
    {
        case 0: newPanel = userControlPanelN0; break;
        case 1: newPanel = userControlPanelN1; break;
        // etc...
    }
    if (newPanel != null)
    {
        if (mActivePanel != null)
        {
            mActivePanel.Hide();
            this.Controls.Remove(mActivePanel);
        }
        newPanel.Show();
        newPanel.Dock = DockStyle.Fill;                
        tableLayoutPanelRight.Controls.Add(newPanel);
        tableLayoutPanelRight.SetColumnSpan(newPanel, 2);

        mActivePanel = newPanel;
    }        
}

private void buttonCancel_Click(object sender, EventArgs e)
{
    bool exit = !statusChanged;

    if (!exit)
        if (MessageBox.Show("Settings changed, close anyway?", 
                "Confirm exit", MessageBoxButtons.YesNo, 
                MessageBoxIcon.Question) == DialogResult.Yes)
            exit = true;

    if (exit)
        this.Close();
}

private void buttonSave_Click(object sender, EventArgs e)
{
    bool isValid = true;

    isValid = isValid && userControlPanelN0.IsValid();
    isValid = isValid && userControlPanelN1.IsValid();

    if (isValid)
    {
        userControlPanelN0.Save();
        userControlPanelN1.Save();
        buttonSave.Enabled = false;
    }
    else
        MessageBox.Show("No valid settings specified", "ERROR", 
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
}

Notice that AddEnableSaveOnChanges take all the interested controls inside the panel binding the EnableSave function on any value changes. 

Here are some previews:

Image 2

Image 3

That's all!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Italy Italy
Creator of:
Impulse Media Player http://impulsemediaplayer.codeplex.com
Audio Pitch & Shift http://audiops.codeplex.com
Ultimate Music Tagger http://umtagger.codeplex.com
Modern Log Viewer http://modernlogviewer.codeplex.com
Pitch Tuner http://pitchtuner.codeplex.com
Modern Audio Tagger http://modernaudiotagger.codeplex.com
Win Log Inspector http://windowsloganalyzer.com/win-log-inspector/
Win Log Analyzer http://windowsloganalyzer.com/win-log-analyzer/

Comments and Discussions

 
QuestionWorks Great Pin
Luis Ricardo Delgado Cortés12-Feb-14 16:59
Luis Ricardo Delgado Cortés12-Feb-14 16:59 
Thanks Fabrizio, the code works great.
AnswerRe: Works Great Pin
Fabrizio Stellato12-Feb-14 22:46
Fabrizio Stellato12-Feb-14 22:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.