deleyd
asked on
WinForms Tabbed Interface configured as Tree of Tabs
I have a WinForms project where the Form has a bunch of tabs configured something like this:
Here the user has selected "tabPage1", and within that TabPage they selected "tabPage4", and within that TabPage they selected "tabPgae12".
Now I want a textBox at the bottom that displays which innermost tab has been selected. (i.e. tabPage12 in the image above.)
I'm thinking the tabs really form a tree like structure:
I'm wondering if I should somehow place the tabs in a tree like data structure. Would that help me figure out which tab is the selected in the tree?
WinForms (at least as this project is currently configured) doesn't seem to have nice separation of View. Is there a design pattern that will give us better separation of View for WinForms?
Is there a clean way to design this program?
Currently it seems like I would have to manually sift through all the tabs, figure out which tab {1,2} is selected, then based on that figure out which tab {3,4,5} is selected, then based on that figure out which tab {10,11,12,13} is selected. Crawling through the View like that seems tedious and wrong. Is there a better way the TextBox at the bottom can figure out which tab is selected and display that number?
Here the user has selected "tabPage1", and within that TabPage they selected "tabPage4", and within that TabPage they selected "tabPgae12".
Now I want a textBox at the bottom that displays which innermost tab has been selected. (i.e. tabPage12 in the image above.)
I'm thinking the tabs really form a tree like structure:
I'm wondering if I should somehow place the tabs in a tree like data structure. Would that help me figure out which tab is the selected in the tree?
WinForms (at least as this project is currently configured) doesn't seem to have nice separation of View. Is there a design pattern that will give us better separation of View for WinForms?
Is there a clean way to design this program?
Currently it seems like I would have to manually sift through all the tabs, figure out which tab {1,2} is selected, then based on that figure out which tab {3,4,5} is selected, then based on that figure out which tab {10,11,12,13} is selected. Crawling through the View like that seems tedious and wrong. Is there a better way the TextBox at the bottom can figure out which tab is selected and display that number?
As stated above, you can bind to the Selected event in order to determine which tab is selected. As for your other question, each TabPage has a parent which is a TabControl. You can use the Parent property in order to get the branch associated with the selected tab; e.g. -
Form1.cs -
HTH,
-saige-
Form1.cs -
using System.Windows.Forms;
namespace EE_Q29214980
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void OnSelected(object sender, TabControlEventArgs e)
{
var tab = sender as TabControl;
textBox1.Text = tab.GetParents();
}
}
static class Extensions
{
public static string GetParents(this TabControl control)
{
var results = default(string);
results = $"{control.SelectedTab.Name}{(control.Parent != null && control.Parent is TabPage ? $"; {((control.Parent as TabPage).Parent as TabControl).GetParents()}" : "")}";
return results;
}
}
}
Form1.Designer.cs -
namespace EE_Q29214980
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.textBox1 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.tabControl2 = new System.Windows.Forms.TabControl();
this.tabPage3 = new System.Windows.Forms.TabPage();
this.tabPage4 = new System.Windows.Forms.TabPage();
this.tabPage5 = new System.Windows.Forms.TabPage();
this.tabControl3 = new System.Windows.Forms.TabControl();
this.tabPage6 = new System.Windows.Forms.TabPage();
this.tabPage7 = new System.Windows.Forms.TabPage();
this.tabPage8 = new System.Windows.Forms.TabPage();
this.tabPage9 = new System.Windows.Forms.TabPage();
this.tabControl5 = new System.Windows.Forms.TabControl();
this.tabPage14 = new System.Windows.Forms.TabPage();
this.tabPage15 = new System.Windows.Forms.TabPage();
this.tabPage16 = new System.Windows.Forms.TabPage();
this.tabPage17 = new System.Windows.Forms.TabPage();
this.tabControl4 = new System.Windows.Forms.TabControl();
this.tabPage10 = new System.Windows.Forms.TabPage();
this.tabPage11 = new System.Windows.Forms.TabPage();
this.tabPage12 = new System.Windows.Forms.TabPage();
this.tabPage13 = new System.Windows.Forms.TabPage();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
this.tabPage2.SuspendLayout();
this.tabControl2.SuspendLayout();
this.tabPage4.SuspendLayout();
this.tabControl3.SuspendLayout();
this.tabPage9.SuspendLayout();
this.tabControl5.SuspendLayout();
this.tabControl4.SuspendLayout();
this.SuspendLayout();
//
// splitContainer1
//
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
this.splitContainer1.Name = "splitContainer1";
this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
//
// splitContainer1.Panel1
//
this.splitContainer1.Panel1.Controls.Add(this.tabControl1);
//
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.label1);
this.splitContainer1.Panel2.Controls.Add(this.textBox1);
this.splitContainer1.Size = new System.Drawing.Size(658, 322);
this.splitContainer1.SplitterDistance = 287;
this.splitContainer1.TabIndex = 0;
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(92, 3);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(554, 20);
this.textBox1.TabIndex = 0;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 6);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(74, 13);
this.label1.TabIndex = 1;
this.label1.Text = "Selected Tab:";
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl1.Location = new System.Drawing.Point(0, 0);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(658, 287);
this.tabControl1.TabIndex = 0;
this.tabControl1.Selected += new System.Windows.Forms.TabControlEventHandler(this.OnSelected);
//
// tabPage1
//
this.tabPage1.Controls.Add(this.tabControl2);
this.tabPage1.Location = new System.Drawing.Point(4, 22);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(650, 261);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "tabPage1";
this.tabPage1.UseVisualStyleBackColor = true;
//
// tabPage2
//
this.tabPage2.Controls.Add(this.tabControl3);
this.tabPage2.Location = new System.Drawing.Point(4, 22);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(650, 261);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "tabPage2";
this.tabPage2.UseVisualStyleBackColor = true;
//
// tabControl2
//
this.tabControl2.Controls.Add(this.tabPage3);
this.tabControl2.Controls.Add(this.tabPage4);
this.tabControl2.Controls.Add(this.tabPage5);
this.tabControl2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl2.Location = new System.Drawing.Point(3, 3);
this.tabControl2.Name = "tabControl2";
this.tabControl2.SelectedIndex = 0;
this.tabControl2.Size = new System.Drawing.Size(644, 255);
this.tabControl2.TabIndex = 0;
this.tabControl2.Selected += new System.Windows.Forms.TabControlEventHandler(this.OnSelected);
//
// tabPage3
//
this.tabPage3.Location = new System.Drawing.Point(4, 22);
this.tabPage3.Name = "tabPage3";
this.tabPage3.Padding = new System.Windows.Forms.Padding(3);
this.tabPage3.Size = new System.Drawing.Size(636, 229);
this.tabPage3.TabIndex = 0;
this.tabPage3.Text = "tabPage3";
this.tabPage3.UseVisualStyleBackColor = true;
//
// tabPage4
//
this.tabPage4.Controls.Add(this.tabControl4);
this.tabPage4.Location = new System.Drawing.Point(4, 22);
this.tabPage4.Name = "tabPage4";
this.tabPage4.Padding = new System.Windows.Forms.Padding(3);
this.tabPage4.Size = new System.Drawing.Size(636, 229);
this.tabPage4.TabIndex = 1;
this.tabPage4.Text = "tabPage4";
this.tabPage4.UseVisualStyleBackColor = true;
//
// tabPage5
//
this.tabPage5.Location = new System.Drawing.Point(4, 22);
this.tabPage5.Name = "tabPage5";
this.tabPage5.Padding = new System.Windows.Forms.Padding(3);
this.tabPage5.Size = new System.Drawing.Size(636, 229);
this.tabPage5.TabIndex = 2;
this.tabPage5.Text = "tabPage5";
this.tabPage5.UseVisualStyleBackColor = true;
//
// tabControl3
//
this.tabControl3.Controls.Add(this.tabPage6);
this.tabControl3.Controls.Add(this.tabPage7);
this.tabControl3.Controls.Add(this.tabPage8);
this.tabControl3.Controls.Add(this.tabPage9);
this.tabControl3.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl3.Location = new System.Drawing.Point(3, 3);
this.tabControl3.Name = "tabControl3";
this.tabControl3.SelectedIndex = 0;
this.tabControl3.Size = new System.Drawing.Size(644, 255);
this.tabControl3.TabIndex = 0;
this.tabControl3.Selected += new System.Windows.Forms.TabControlEventHandler(this.OnSelected);
//
// tabPage6
//
this.tabPage6.Location = new System.Drawing.Point(4, 22);
this.tabPage6.Name = "tabPage6";
this.tabPage6.Padding = new System.Windows.Forms.Padding(3);
this.tabPage6.Size = new System.Drawing.Size(636, 229);
this.tabPage6.TabIndex = 0;
this.tabPage6.Text = "tabPage6";
this.tabPage6.UseVisualStyleBackColor = true;
//
// tabPage7
//
this.tabPage7.Location = new System.Drawing.Point(4, 22);
this.tabPage7.Name = "tabPage7";
this.tabPage7.Padding = new System.Windows.Forms.Padding(3);
this.tabPage7.Size = new System.Drawing.Size(636, 229);
this.tabPage7.TabIndex = 1;
this.tabPage7.Text = "tabPage7";
this.tabPage7.UseVisualStyleBackColor = true;
//
// tabPage8
//
this.tabPage8.Location = new System.Drawing.Point(4, 22);
this.tabPage8.Name = "tabPage8";
this.tabPage8.Padding = new System.Windows.Forms.Padding(3);
this.tabPage8.Size = new System.Drawing.Size(636, 229);
this.tabPage8.TabIndex = 2;
this.tabPage8.Text = "tabPage8";
this.tabPage8.UseVisualStyleBackColor = true;
//
// tabPage9
//
this.tabPage9.Controls.Add(this.tabControl5);
this.tabPage9.Location = new System.Drawing.Point(4, 22);
this.tabPage9.Name = "tabPage9";
this.tabPage9.Padding = new System.Windows.Forms.Padding(3);
this.tabPage9.Size = new System.Drawing.Size(636, 229);
this.tabPage9.TabIndex = 3;
this.tabPage9.Text = "tabPage9";
this.tabPage9.UseVisualStyleBackColor = true;
//
// tabControl5
//
this.tabControl5.Controls.Add(this.tabPage14);
this.tabControl5.Controls.Add(this.tabPage15);
this.tabControl5.Controls.Add(this.tabPage16);
this.tabControl5.Controls.Add(this.tabPage17);
this.tabControl5.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl5.Location = new System.Drawing.Point(3, 3);
this.tabControl5.Name = "tabControl5";
this.tabControl5.SelectedIndex = 0;
this.tabControl5.Size = new System.Drawing.Size(630, 223);
this.tabControl5.TabIndex = 0;
this.tabControl5.Selected += new System.Windows.Forms.TabControlEventHandler(this.OnSelected);
//
// tabPage14
//
this.tabPage14.Location = new System.Drawing.Point(4, 22);
this.tabPage14.Name = "tabPage14";
this.tabPage14.Padding = new System.Windows.Forms.Padding(3);
this.tabPage14.Size = new System.Drawing.Size(622, 197);
this.tabPage14.TabIndex = 0;
this.tabPage14.Text = "tabPage14";
this.tabPage14.UseVisualStyleBackColor = true;
//
// tabPage15
//
this.tabPage15.Location = new System.Drawing.Point(4, 22);
this.tabPage15.Name = "tabPage15";
this.tabPage15.Padding = new System.Windows.Forms.Padding(3);
this.tabPage15.Size = new System.Drawing.Size(622, 197);
this.tabPage15.TabIndex = 1;
this.tabPage15.Text = "tabPage15";
this.tabPage15.UseVisualStyleBackColor = true;
//
// tabPage16
//
this.tabPage16.Location = new System.Drawing.Point(4, 22);
this.tabPage16.Name = "tabPage16";
this.tabPage16.Padding = new System.Windows.Forms.Padding(3);
this.tabPage16.Size = new System.Drawing.Size(622, 197);
this.tabPage16.TabIndex = 2;
this.tabPage16.Text = "tabPage16";
this.tabPage16.UseVisualStyleBackColor = true;
//
// tabPage17
//
this.tabPage17.Location = new System.Drawing.Point(4, 22);
this.tabPage17.Name = "tabPage17";
this.tabPage17.Padding = new System.Windows.Forms.Padding(3);
this.tabPage17.Size = new System.Drawing.Size(622, 197);
this.tabPage17.TabIndex = 3;
this.tabPage17.Text = "tabPage17";
this.tabPage17.UseVisualStyleBackColor = true;
//
// tabControl4
//
this.tabControl4.Controls.Add(this.tabPage10);
this.tabControl4.Controls.Add(this.tabPage11);
this.tabControl4.Controls.Add(this.tabPage12);
this.tabControl4.Controls.Add(this.tabPage13);
this.tabControl4.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl4.Location = new System.Drawing.Point(3, 3);
this.tabControl4.Name = "tabControl4";
this.tabControl4.SelectedIndex = 0;
this.tabControl4.Size = new System.Drawing.Size(630, 223);
this.tabControl4.TabIndex = 1;
this.tabControl4.Selected += new System.Windows.Forms.TabControlEventHandler(this.OnSelected);
//
// tabPage10
//
this.tabPage10.Location = new System.Drawing.Point(4, 22);
this.tabPage10.Name = "tabPage10";
this.tabPage10.Padding = new System.Windows.Forms.Padding(3);
this.tabPage10.Size = new System.Drawing.Size(622, 197);
this.tabPage10.TabIndex = 0;
this.tabPage10.Text = "tabPage10";
this.tabPage10.UseVisualStyleBackColor = true;
//
// tabPage11
//
this.tabPage11.Location = new System.Drawing.Point(4, 22);
this.tabPage11.Name = "tabPage11";
this.tabPage11.Padding = new System.Windows.Forms.Padding(3);
this.tabPage11.Size = new System.Drawing.Size(622, 197);
this.tabPage11.TabIndex = 1;
this.tabPage11.Text = "tabPage11";
this.tabPage11.UseVisualStyleBackColor = true;
//
// tabPage12
//
this.tabPage12.Location = new System.Drawing.Point(4, 22);
this.tabPage12.Name = "tabPage12";
this.tabPage12.Padding = new System.Windows.Forms.Padding(3);
this.tabPage12.Size = new System.Drawing.Size(622, 197);
this.tabPage12.TabIndex = 2;
this.tabPage12.Text = "tabPage12";
this.tabPage12.UseVisualStyleBackColor = true;
//
// tabPage13
//
this.tabPage13.Location = new System.Drawing.Point(4, 22);
this.tabPage13.Name = "tabPage13";
this.tabPage13.Padding = new System.Windows.Forms.Padding(3);
this.tabPage13.Size = new System.Drawing.Size(622, 197);
this.tabPage13.TabIndex = 3;
this.tabPage13.Text = "tabPage13";
this.tabPage13.UseVisualStyleBackColor = true;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(658, 322);
this.Controls.Add(this.splitContainer1);
this.Name = "Form1";
this.Text = "Form1";
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false);
this.splitContainer1.Panel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
this.splitContainer1.ResumeLayout(false);
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.tabPage2.ResumeLayout(false);
this.tabControl2.ResumeLayout(false);
this.tabPage4.ResumeLayout(false);
this.tabControl3.ResumeLayout(false);
this.tabPage9.ResumeLayout(false);
this.tabControl5.ResumeLayout(false);
this.tabControl4.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.SplitContainer splitContainer1;
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.TabControl tabControl2;
private System.Windows.Forms.TabPage tabPage3;
private System.Windows.Forms.TabPage tabPage4;
private System.Windows.Forms.TabPage tabPage5;
private System.Windows.Forms.TabPage tabPage2;
private System.Windows.Forms.TabControl tabControl3;
private System.Windows.Forms.TabPage tabPage6;
private System.Windows.Forms.TabPage tabPage7;
private System.Windows.Forms.TabPage tabPage8;
private System.Windows.Forms.TabPage tabPage9;
private System.Windows.Forms.TabControl tabControl5;
private System.Windows.Forms.TabPage tabPage14;
private System.Windows.Forms.TabPage tabPage15;
private System.Windows.Forms.TabPage tabPage16;
private System.Windows.Forms.TabPage tabPage17;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.TabControl tabControl4;
private System.Windows.Forms.TabPage tabPage10;
private System.Windows.Forms.TabPage tabPage11;
private System.Windows.Forms.TabPage tabPage12;
private System.Windows.Forms.TabPage tabPage13;
}
}
Produces the following output:HTH,
-saige-
ASKER
K the problem is, if the user switches to "tabPage2", and then back to "tabPage1", the "SelectedChanged" event tells me the user clicked "tabPage2" and then "tabPage1", but doesn't tell me that tabPage12 is still the selected tab under tabPage1.
I think I need to build a data model of the tab tree, with pointers to the child tabs, so I can start at the top of the tree and navigate my way down to the farthest selected child. I guess an external tree of the WinForm TabControls is what I need?
I think I need to build a data model of the tab tree, with pointers to the child tabs, so I can start at the top of the tree and navigate my way down to the farthest selected child. I guess an external tree of the WinForm TabControls is what I need?
That is because the selected TabPage is TabPage1. TabPage12 is no longer selected.
-saige-
-saige-
ASKER
Yea technically. I think the original authors didn't fully think through the details when this was originally designed. It doesn't make any sense to have "tabPage1" selected and focused, which is what we currently have, because the page being displayed with all the content is actually "tabPage12".
A tree is what we really have. I wonder if a TreeView can be formatted to look like a stack of tabs. Can we replace our tabs with a TreeView somehow without redesigning the look?
A tree is what we really have. I wonder if a TreeView can be formatted to look like a stack of tabs. Can we replace our tabs with a TreeView somehow without redesigning the look?
It might sound silly but why do you actually want to display the ' tab ' in a textbox?
What you might want is that when a 'child' tab is selected it sets a value in its parent tab and you can use this to display things when the event fires.
What you might want is that when a 'child' tab is selected it sets a value in its parent tab and you can use this to display things when the event fires.
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.tabcontrol.selected?view=net-5.0
So you can change the text box contents in response to that.