Use a TreeView to display property pages or option pages in C#

If you open Visual Studio's Tools menu and select the Options command, you'll see an enormous set of options that you can set. The TreeView on the left groups the option pages. You dig through the TreeView to find an option category and a page within the category, and then the area on the right displays that page's options.

This provides a useful alternative to the TabControl.

If you open Visual Studio's Project menu and select Properties at the bottom, you can see an example tab-based property pages. Generally this style is easier to use because it lets you see all of the categories on the tabs all at once. The TreeView style is most appropriate when you have a huge number of pages so you can't practically put them all in separate tabs.

Building a TreeView is easy enough. The tougher questions are:

  1. How do you associate the nodes in the tree with the property pages?
  2. How do you build the property pages at design time?
  3. How do you display the selected property page at run time?
  4. How do you save and restore the settings on the property pages?

1. How do you associate the nodes in the tree with the property pages?

Edit a TreeView control at design time to build the categories and sub-categories that you want. Set each node's Tag property to the index of the property page that you want it to display.

2. How do you build the property pages at design time?

This example uses a TabControl to hold the property pages because it is easy to use and lets you add controls to its pages at design time. You cannot simply have the TreeView select the appropriate tab, however, because the TabControl displays tabs that you probably don't want. Even if you make the tabs owner-drawn and give them the smallest size possible (1x1 pixel), you see an annoying little bump where the tabs would be.

To avoid that, the example moves the contents of the tabs out of the TabControls onto the form.

Put a Panel control inside each tab and put all of the tab's other controls inside the Panel. When the program's main form loads, the following code moves the Panels onto the form.

// Move the Panels out of the TabControl.
tabControl1.Visible = false;
foreach (TabPage page in tabControl1.TabPages)
{
// Add the Panel to the list.
Panel panel = page.Controls[0] as Panel;
Panels.Add(panel);

// Reparent and move the Panel.
panel.Parent = tabControl1.Parent;
panel.Location = tabControl1.Location;
panel.Visible = false;
}

3. How do you display the selected property page at run time?

When the user selects a TreeView node, the following code executes. The AfterSelect event handler converts the node's Tag property into an integer and passes it to the DisplayPanel function.

DisplayPanel hides the previously visible panel and displays the one with the indicated index.

// Display the appropriate Panel.
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
int index = int.Parse(e.Node.Tag.ToString());
DisplayPanel(index);
}

// Display the appropriate Panel.
private void DisplayPanel(int index)
{
if (Panels.Count < 1) return;

// If this is the same Panel, do nothing.
if (VisiblePanel == Panels[index]) return;

// Hide the previously visible Panel.
if (VisiblePanel != null) VisiblePanel.Visible = false;

// Display the appropriate Panel.
Panels[index].Visible = true;
VisiblePanel = Panels[index];
}

4. How do you save and restore the settings on the property pages?

The form's Load and FormClosing event handlers call the RegistryTools.LoadAllSettings and RegistryTools.SaveAllSettings functions described in the article Easily save and restore all of a form's settings and the values of its controls in the Registry in C#. These functions let the program easily save and restore all of the values on every option page quickly and easily.

Download the program to see additional details. Note that the program doesn't do anything with the settings. It just saves and restores them.

   

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments

  • 2/20/2013 10:12 PM Todd wrote:
    Thanks for this article. It was just what I needed.

    I did make some minor modifications that I think are a nice touch:

    I created a DisplayPanels class. It has a:

         private Dictionary<string, TabPage> panelsDictionary; 

    that I use to store all the panels.

    For the key I actually use a string in the Tag such as "Results". I set the tag in the TabPage and set a matching tag in the Node in the Tree.

    Thanks again for the cool post.

    All the best,

    Todd

    [Note: Sometimes the web site messes up comments that contain code. I tried to fix this but if I got it wrong, Todd, let me know and I'll fix it. Rod]
    Reply to this
Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.