Tab system using panels - c#

I'm trying to make it to where a panel becomes visible and it sent to the front so it can be seen and interacted with, like this.
private void SettingsButton_Click(object sender, EventArgs e)
{
SettingsPanel.Visible = true;
SettingsPanel.BringToFront();
}
The problem is that after clicking a few of the buttons, it will either display the wrong panel or none at all. Is there a way to fix this?
EDIT: Before y'all ask, i'm using WinForms.

OK, so I was wrong, WinForms is smarter than I thought. Here's a test you can do. I'm not exactly sure what you are trying to do, but this should help you along. To start, we're going to build a small WinForms app. With one exception, we aren't going to set any properties of the controls we drop on the screen:
Create a new WinForms app
In the designer, drop a Panel (which will be named panel1) on the form
In the properties pane, set the BorderStyle to FixedSingle (that's the only property we are going to set)
Make two copies of that panel (panel2 and panel3). Position them so that panels do not overlap at all.
On each panel drop a couple of controls (I put labels (labels 1-3) and textboxes (also 1-3)) on each one
Beside each panel (arranged so that there is no overlap) drop three buttons on the form (buttons 1-3) make it so that visually, each button is associated with the similarly numbered panel
Duplicate panel3 including its contained controls (so that you get panel4, label4 and textbox4). Position the duplicate so that it significantly overlaps panel 3
Now we're going to look at the code that the designer creates for your form. Don't mess with this code (you can, but if you don't know what you are doing, it can turn out bad - and, we're keeping this simple).
In the Solution Explorer click the unfilled triangle to the left of Form1.cs. Note that it rotates and turns solid. Also note that Form1.Designer.cs is displayed. That's a normally hidden source file that contains all the designer created code that corresponds with the form and the controls you dropped on it.
Open Form1.Designer.cs
Click the little grey plus sign icon next to Windows Form Designer generated code
Inspect the file. Note that every action you did in the designer has a corresponding line of code in the Designer.cs file (more or less)
Look at the code for one of the panels (say panel1).
See that it includes:
this.panel1.Controls.Add(this.textBox1);
this.panel1.Controls.Add(this.label1);
Scroll all the way down to the Form1 code and see that the panels and buttons get added to the Form's Controls collection:
Like:
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.panel4);
this.Controls.Add(this.panel3);
this.Controls.Add(this.panel2);
this.Controls.Add(this.panel1);
Note that the order is reversed. The order is important, it sets the Z-Order (i.e., what overlaps what) for the form and the controls on the form.
Wiring up the buttons
Select all three buttons and press <Enter>. This will open the Form1.cs file and generate three button click handlers that you can fill in.
Use this code for the three button handlers:
private void button1_Click(object sender, EventArgs e) {
var wasVisible = panel1.Visible;
panel1.Visible = !wasVisible;
}
private void button2_Click(object sender, EventArgs e) {
panel2.BringToFront();
}
private void button3_Click(object sender, EventArgs e) {
panel3.BringToFront();
}
The first one will toggle the first panel's visibility (I put in an extra variable so you can set a breakpoint and see what's going on). The second one brings panel2 to the front, changing its Z-Order (it's called Z-Order because the position on the screen is measure in X and Y, which the overlap position is related to the "depth" of the screen, or the Z-coordinate). The last one does the same thing to panel3.
Run the program.
When you press the first button, the first panel and its controls disappear (this surprised me, WinForms is smarter than I thought)
When you press the second button, nothing appears to happen. This is because the only thing that panel2 intersects is the form, and panel2 already covers the form, so you don't see any effect. (and because WinForms is smarter than I thought)
When you press the third button, panel2 (and it's controls) jump to the front of the stack of controls, covering the intersecting part of panel4.
Does this help you understand how Visible and BringToFront() work?

What you're describing is similar to a TabControl alternative. Here's an example:
You can manage the current panel simply by making it visible and docked to fill. Hide the other panels.
public partial class FormTabsAlternative
: Form
{
int m_current = 0;
List<Panel> m_tabs = new List<Panel>();
public FormTabsAlternative()
{
InitializeComponent();
AddTab(pnl1);
AddTab(pnl2);
AddTab(pnl3);
AddTab(pnl4);
SetUpTabsAndButtons();
}
private void AddTab(Panel pnl)
{
m_tabs.Add(pnl);
pnl.Dock = DockStyle.Fill;
}
private void OnLeftClick(object sender, EventArgs e)
{
if (m_current > 0)
{
m_current--;
SetUpTabsAndButtons();
}
}
private void OnRightClick(object sender, EventArgs e)
{
if (m_current < m_tabs.Count - 1)
{
m_current++;
SetUpTabsAndButtons();
}
}
private void SetUpTabsAndButtons()
{
for (int index = 0; index < m_tabs.Count; index++)
{
var panel = m_tabs[index];
panel.Visible = index == m_current;
}
btnLeft .Enabled = m_current > 0;
btnRight.Enabled = m_current < m_tabs.Count - 1;
}
}

Related

Need Methodology to replicate a panel with button and shifting other buttons in a same time

Here is my form
If I click on "Add" on the first panel I want to create "Strategy1_2" just below the first and shift all others panels down.
If I click again I want to create Strategy1_3 (...)
I know how to create a button but not how to duplicate a entire panel.
Here is my code for a button is it far from this procedure ?
private void addstrat1_i_Click(object sender, EventArgs e)
{
panel3strat.Width += 200;
Button addstrat1_2 = new Button();
addstrat3_2.Size = new Size(210, 41);
addstrat1_2.Location = new Point(31,89);
addstrat1_2.Visible = true;
panel1strat.Controls.Add(addstrat3_2);
}
The best way would be that you create a UserControl for your strategy panel. You can then insert the UserControls to a FlowLayoutPanel. This will resolve your issue with placing controls exactly and to create a copy of some panels.
Be aware that you can run out of resources (e.g. windows handles) when adding to much controls on your form. This can be solved by only showing a certain amount of controls and shifting the data through this "fixed" controls while scrolling.
I recommend having two methods: CreatePanelBlock() that will issue a UserControl that you'll add to your container, and BindPanelWithData(...) that will setup the dependencies.
Remember, you may make your panel as a custom control.

Windows Forms - how to exclude button from the whole set

I have a Windows Form that contains only buttons. The final goal is to make a simple logic game I saw but for now the problem is that I want to perform different actions when my New button is clicked, but now it is part from all the buttons in the form so sometimes an action is performed on him too which should not happen. To make myself clear I have two screenshots :
So this is how I want it to be - I have a matrix - 3x3 (in this case, at the end it can be NxN). By clicking New I want to be able to do various things one of which is to make N buttons colored red. What happens now is sometimes my New button also get painted because I go over the buttons like this:
foreach (Control c in this.Controls)
{
if (c is Button)
{
...
and thus sometimes New get selected too, so I end up with this:
What I'm thinking right now is just to perform check whenever I need in the code and exclude my New button explicitly but I don't think it's a good way cause I may end up with a code doing this thing in a lot of places in my program so what is the right solution in this case? If some code is needed please ask.
Quite possibly the easiest solution is to put the Grid in its own Panel (pnlGrid). Put all of the buttons in there, then you could just do the following instead:
foreach (Control ctl in pnlGrid.Controls) {
if (ctl is Button) {
// Do your logic here
}
}
Instead of looping through controls, add all the matrix buttons to a list, and have the new button separated:
private Button[] buttons;
private Button newButton;
Now you can add as many buttons as you'd like to:
for (int i = 0; i < 9; i++)
{
buttons[i] = new Button();
buttons[i].Text = "Button" + i;
Controls.Add(buttons[i])
}
And lastly, your New button will loop through buttons:
private void newButton_Click(object sender, EventArgs e)
{
foreach (Button b in buttons)
{
...
}
}
You could inherit from the button class. Make your own button, use this control (that will have the same functionality that the parent one) for the set, and check for it when you iterate over the controls.
You could also use the Tag property for this pourpose, but I think that inherit will be more clear, adding semantic meaning to your code.

how can i achieve this in c#

i'm developing a windows form application.in the form, the left part is a tree menu, and the right part is show area. how can i change the show area according to what i click on the tree menu.
(source: 126.net)
i use treenode class to implement treemenu like this:
System.Windows.Forms.TreeNode treeNode27 = new System.Windows.Forms.TreeNode("basic operation");
what i try to do is use several panels. each panel bounds to a menu item. by setting the visible property, i can achieve that goal. but it is too inconvenient.especially when i try to design each panel.
any good suggestion?
You could design each "Panel" as a new User Control. That way you can design all of the "panels / areas" on their own, independently of the Main Form.
On your Main Form, create a single panel for the right hand side area and add all of the controls to that one panel.
Then when the TreeNode selection event happens you can set all the user controls to .Visible = false; except for the one you are showing and set that to .Visible = true; and .Dock = DockStyle.Fill;
What you need is an event handler that will be called at the time of the user clicking the treeview (Use TreeView from the toolBox). You can do that by selecting the treeview on the design page and under properties click on Events. Then select NodeMouseDoubleClick or NodeMouseClick depending upon what you want. Below is a code that captures the values selected...Enjoy...;)
private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
{
if (treeView1.SelectedNode.Level == 2)
{
//text on the first level
string text = treeView1.SelectedNode.Text;
}
else if (treeView1.SelectedNode.Level == 1)
{
//text on the second level
string text = treeView1.SelectedNode.Text;
}
}

c# .NET - Tabpage margin

I have a tabcontrol with 3 tabpages. I need to add a left margin to the first tabpage ( so move all tabpages move right of 200px ). How can I do it??
Using Visual Studio 2008 / c#
EDIT Reading again I think you're more looking for the controls on each page to be on the right of the tabs rather than moving the buttons.
As Hans suggests a panel would be the easiest way. But it's not pretty.
private void Form1_Load(object sender, EventArgs e)
{
// Create spacer tab with a name long enough to reach the 200px mark
TabPage spacer = new TabPage("..............................................................");
tabControl1.TabPages.Insert(0, spacer);
// Create a panel at the same location of the tab control.
Panel spacerBlock = new Panel();
spacerBlock.Name = "spacer";
spacerBlock.Location = tabControl1.Location;
spacerBlock.Width = 198;
spacerBlock.Height = 20;
this.Controls.Add(spacerBlock);
spacerBlock.BringToFront();
}
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
// Ensure the user can't use the keyboard to somehow select the spacer tab.
if (tabControl1.SelectedIndex == 0)
tabControl1.SelectedIndex = 1;
// Check if the second (first I guess) tab is selected and adjust the panel to keep the look consistant.
if (tabControl1.SelectedIndex == 1)
this.Controls["spacer"].Width = 198;
else
this.Controls["spacer"].Width = 200;
}
You'll want to make sure the tab isn't selectable by the user via keyboard shortcuts thus the index change check.
Also note the panel will have to have its width adjusted if the second (first in your case) tab is selected due to the 3d GUI effect.
Honestly the hassle of taking into account the appearance settings of the end user to ensure the spacer tab's text and the panel width are correct length doesn't really make up for fancy look IMHO.
Only other option I could think of would be a tab panel with a 16px height. Again this would have to be adjusted depending on the end users appearance settings, not to mention the excess overhead in getting it all working.
If it's the AjaxControlToolkit tab control, add this CSS class:
.TabContainer .ajax__tab_header
{
padding-left: 200px;
}
you would need a work-around for that because tab pages can't be moved. You might wanna place a groupbox inside the tabpage and then you can add all the controls inside the groupbox as you desire...
// tabPage 1
this.tabPage1.Controls.Add(this.groupBox1);
// groupBox1
this.groupBox1.Location = new System.Drawing.Point(200,6);
this.groupBox1.Controls.Add(this.textBox1);
this.groupBox1.Controls.Add(this.AnyControls); //etc

ContextMenuStrip renders at top left Windows

When i render contextmenustrip, it gets render at the top left of my PC Screen. I have a listview, which contains 5-6 items and on right click of each item, the context Menu strip gets displayed.Also i need to change the color of context menu strip including backgrounds and text as well.
Thanks in advance!
By far the simplest way is to just set the ListView.ContextMenuStrip property to your CMS, everything is automatic then. You can do so in the designer.
If you need a custom handler for some reason, to check if the right item was clicked for example, then you can call the Show() method property with code like this:
private void listView1_MouseClick(object sender, MouseEventArgs e) {
if (allowContextMenu(listView1.SelectedItems) {
contextMenuStrip1.Show(listView1, e.Location);
}
}
You haven't shown any code, but if you're not calling the Show overload that takes a control as a parameter, the new Point(0, 0) that your obviously passing will put the menu in the upper left of the screen.

Categories