I am developing a form with multiple options that simulates a signup form, and I want to display some tips and descriptions in a RichTextBox located by the options when the user's mouse hover by it's GroupBoxes.
Since I am fairly new to programming, I don't know if getting all the controls names one by one is the optimal, so I want to grab the controls' names inside of the tabControl control that I am using to organize everything.
private void TabControl1_MouseHover(object sender, EventArgs e)
{
foreach(Control c in this.Controls)
{
string name = c.Name;
TooltipText(name);
}
}
And I also have a method where I will write the text that will be displayed in the RichTextBox.
private string TooltipText(string name)
{
if(name == "Name:")
{
return "blabla";
}
else
{
return "none";
}
}
I've tried a generic method to show a message box if the control was detected and, as I suspected, nothing showed up:
private void TooltipText(string name)
{
if(name == "LBL_Name")
{
MessageBox.Show("hey");
return;
}
}
How can I properly detect the Groupboxes or other types of Controls inside of the TabControl control, and also display the text in the box beside it?
You don't have to create your own Tool Tips. The .net WinForms provides a ToolTip class. https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.tooltip?view=netframework-4.8
I added 2 radio buttons to a group box in design view.
Try it and see.
private void Form1_Load(object sender, EventArgs e)
{
ToolTip tip = new ToolTip();
tip.AutoPopDelay = 5000;
tip.InitialDelay = 1000;
tip.ReshowDelay = 500;
tip.SetToolTip(radioButton1, "Choose to Add Onions");
tip.SetToolTip(radioButton2, "Choose to Add Pickles");
}
Using VS 2015 and C#...
I have this simple modal Form with just a MaskedTextBox control on it.
Each time after the first that ModalForm is shown with .ShowDialog(), the PromptChar in the control is gone.
To reproduce this issue:
public ModalForm()
{
InitializeComponent();
maskedTextBox1.Mask = "00/00/0000"; // happens with any
maskedTextBox1.TextMaskFormat = MaskFormat.IncludeLiterals;
}
Code for main Form:
public partial class Form1 : Form
{
private ModalForm modalForm = new ModalForm();
private void button1_Click(object sender, EventArgs e)
{
modalForm.ShowDialog();
}
}
The control's prompt appears again when its content changes, but at first view isn't present.
Setting the TextMaskFormat property to IncludePromptAndLiterals could be a solution, but then, .Text has to be cleaned up.
Is there another way to handle this?. Has become necessary for me, that all MaskedTextBox controls must always show its default prompt.
Try this on Form's Shown event,
private void ModalForm_Shown(object sender, EventArgs e){
if (!maskedTextBox1.MaskCompleted) // if there is missing parts it will return false, every false means prompts need in control
{
string tempText = maskedTextBox1.MaskedTextProvider.ToDisplayString(); // get the last value with prompts
maskedTextBox1.Text = "";
maskedTextBox1.Text = tempText; // then set the last value.
}
}
Hope helps,
I have 2 windows forms, they both have same comboboxes with same possible selections. I want to pass selection from one combobox to another on button click.
I am passing values successfully to textboxes but when it comes to combobox, I cant figure it out.
Here is the code example:
Form 2 definition
private double passTxt;
private string passCB;
public double passTxtValue
{
get { return passTxt; }
set { passTxt = value; }
}
public string passCbValue
{
get { return passCB; }
set { passCB = value; }
}
Form 1 send
private void btnPassValues_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.passTxtValue = variable1Form1;
form2.passCbValue = CBForm1.SelectedText;
form2.Show();
}
Form2 - load (open)
private void form2_Load(object sender, EventArgs e)
{
variable1Form2.Text = passTxt.ToString();
CBForm2.SelectedText = passCB;
}
When I check with debugger, the error is in step 2. Form1 send empty string ("") for form2.passCbValue = CBValueForm1.SelectedText;
When I try to use index or value it require cast but then there is an error that it can't be casted. Can someone tell me what i do wrong?
SelectedText represent the current selected text in the TextBox area of a ComboBox with DropDown style (the blue highlighted text). This selection is cleared every time the combobox looses its focus (and when you are in the button click event, the focus is on the button).
The workaround is to pass the SelectedIndex of the combo on form1 (if the two combos are filled with the same items in the same order)
private void btnPassValues_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.passTxtValue = variable1Form1;
form2.passCbIndex = CBValueForm1.SelectedIndex;
form2.Show();
}
In form2 change the property to get an integer instead of a string....
private int passCBIndex;
public int passCbIndex
{
get { return passCBIndex; }
set { passCBIndex = value; }
}
and in your form2 Load event
private void form2_Load(object sender, EventArgs e)
{
....
CBValueForm2.SelectedIndex = passCBIndex;
}
Change it into:
form2.passCbValue = CBValueForm1.SelectedItem.ToString();
//Declare a Global string variable in the Form1
public String testValue;
//Assign the value had in the origin comboBox
testValue = cboOriginValue.Text;
//Create an Form2 Object Type and assign the value in the variable testValue
//to either the textbox or combobox components
Form2 form2 = new Form2();
//Make it visible
form2.Visible = true;
form2.cboVehiculo.Text = tipoAutomovil;
form2.txtRecibe.Text = tipoAutomovil;
When you hit a button or whatever these lines of code being executed you'll have the textboxes or comboboxes components populated with the selected value.
Hope it helps
I have a button which I use all the time as a little pick button next to a combobox. When I click the button I open a larger full list. This side of things work well and I do not have a problem with this..
My problem lies when someone said to me can you change that ugly icon you picked to my nice icon.
I went crap, I have hundreds of these buttons on many forms. So I thought I will create a custom control called PickButton (which is a standard button and heap of default proeprties set) and drop these on the form everywhere instead. In the code of the PickButton custom control I set some properties and the image to the customers nice icon.
So I drop the PickButton from my toolbox onto the form, so far things are looking pretty good and I am feeling a bit clever. Now I think to myself I will change back to my nice icon not the crappy one the customer picked and change the code in the PickButton custom control. But I cannot get rid of that customers icon, because the code when the PickButton run happens before the code in the designer file which has the customers icon.
So my aim was to have a PickButton control and be able to change the icon and other properties in one place and all the properties would be set when an instance of the control is created and displayed on the form.
Was I not so clever and went about achieving the task the wrong way???
This is my PickButton custom control class
public class PickButton : Button
{
public PickButton()
{
InitialiseButton();
}
internal void InitialiseButton()
{
this.ImageAlign = ContentAlignment.MiddleCenter;
this.Image = WindowsFormsApplication1.Properties.Resources.Cancel.ToBitmap();
this.Size = new Size( 28, 28 );
this.Dock = DockStyle.Fill;
this.Margin = new Padding( 0, 2, 2, 0 );
this.Text = string.Empty;
}
}
Now I drop one onto my form and the code in the designer is as follows
//
// pickButton1
//
this.pickButton1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pickButton1.Image = ((System.Drawing.Image)(resources.GetObject("pickButton1.Image")));
this.pickButton1.Location = new System.Drawing.Point(0, 0);
this.pickButton1.Margin = new System.Windows.Forms.Padding(0, 2, 2, 0);
this.pickButton1.Name = "pickButton1";
this.pickButton1.Size = new System.Drawing.Size(284, 262);
this.pickButton1.TabIndex = 0;
this.pickButton1.Text = "pickButton1";
this.pickButton1.UseVisualStyleBackColor = true;
Now I want to change the image so I change my PickButton code to use a different icon
this.Image = WindowsFormsApplication1.Properties.Resources.Browse.ToBitmap();
Run the application andd the first icon is still the one being displayed because of this line of code in the designer file
this.pickButton1.Image = ((System.Drawing.Image)(resources.GetObject("pickButton1.Image")));
The concept of setting all the properties in one place was a good idea, it just wasn't implemented quite right. I would make this class inherit from UserControl instead of from Button. By making it a UserControl, you can use the designer to set all the properties you want, like the default Image for the button. Set that in the designer, then just drag and drop your UserControl from the toolbox onto your forms. If you are only using your "PickButton" control with comboboxes, I would put the combobox on the UserControl as well. If you ever want to change your button image in the future (or any other property for that matter), you will be able to change it in ctlPickButton and that will propogate the changes to all the instances used throughout your project(s).
ctlPickButton:
public partial class ctlPickButton : UserControl
{
public event EventHandler pickButtonClicked;
public ctlPickButton()
{
InitializeComponent();
}
//Allows buttons image to be set in code if necessary
public Image Image
{
get
{
return button1.Image;
}
set
{
if (Image != null)
{
button1.Image = value;
}
}
}
private void button1_Click(object sender, EventArgs e)
{
if (pickButtonClicked != null)
{
pickButtonClicked(sender, e);
}
}
}
Demo Form:
public Form1()
{
InitializeComponent();
ctlPickButton1.pickButtonClicked += new EventHandler(ctlPickButton1_pickButtonClicked);
ctlPickButton2.pickButtonClicked += new EventHandler(ctlPickButton2_pickButtonClicked);
}
void ctlPickButton2_pickButtonClicked(object sender, EventArgs e)
{
if (comboBox2.SelectedItem != null)
{
MessageBox.Show(comboBox2.SelectedItem.ToString());
}
}
void ctlPickButton1_pickButtonClicked(object sender, EventArgs e)
{
if (comboBox1.SelectedItem != null)
{
MessageBox.Show(comboBox1.SelectedItem.ToString());
}
}
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.Items.Add("French");
comboBox1.Items.Add("Spanish");
comboBox1.Items.Add("English");
comboBox1.Items.Add("German");
comboBox2.Items.Add("Pizza");
comboBox2.Items.Add("Hamburger");
comboBox2.Items.Add("Potato");
comboBox2.Items.Add("Chicken");
//Shows how the default image set in the designer can be overwritten for a
//specific instance using the "Image" property
ctlPickButton2.Image = Testbed.Properties.Resources.searchIcon2;
}
}
Image of ctlPickButton in designer
I think I've found a simple, clean solution:
In the CustomButton class (which inherits from System.Windows.Forms.Button), override the Refresh() method, and set the image of the button to the one you want to see:
public class CustomButton : Button
{
public override void Refresh()
{
Image = MyResources.HappyFace;
}
}
In the form that will hold an instance of your CustomButton, simply call customButton.Refresh() in the constructor, after InitializeComponent():
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
customButton.Refresh();
}
}
I've put a demo application up on Github.
Is there a way to disable a tab in a TabControl?
Cast your TabPage to a Control, then set the Enabled property to false.
((Control)this.tabPage).Enabled = false;
Therefore, the tabpage's header will still be enabled but its contents will be disabled.
The TabPage class hides the Enabled property. That was intentional as there is an awkward UI design problem with it. The basic issue is that disabling the page does not also disable the tab. And if try to work around that by disabling the tab with the Selecting event then it does not work when the TabControl has only one page.
If these usability problems do not concern you then keep in mind that the property still works, it is merely hidden from IntelliSense. If the FUD is uncomfortable then you can simply do this:
public static void EnableTab(TabPage page, bool enable) {
foreach (Control ctl in page.Controls) ctl.Enabled = enable;
}
You can simply use:
tabPage.Enabled = false;
This property is not shown, but it works without any problems.
You can program the Selecting event on TabControler to make it impossible to change to a non-editable tab:
private void tabControler_Selecting(object sender, TabControlCancelEventArgs e)
{
if (e.TabPageIndex < 0) return;
e.Cancel = !e.TabPage.Enabled;
}
You could register the "Selecting" event and cancel the navigation to the tab page:
private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (e.TabPage == tabPage2)
e.Cancel = true;
}
Another idea is to put all the controls on the tabpage in a Panel control and disable the panel! Smiley
You could also remove the tabpage from the tabControl1.TabPages collection. That would hide the tabpage.
Credits go to littleguru # Channel 9.
Presumably, you want to see the tab in the tab control, but you want it to be "disabled" (i.e., greyed, and unselectable). There is no built-in support for this, but you can override the drawing mechanism to give the desired effect.
An example of how to do this is provided here.
The magic is in this snippet from the presented source, and in the DisableTab_DrawItem method:
this.tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
this.tabControl1.DrawItem += new DrawItemEventHandler( DisableTab_DrawItem );
Extending upon Cédric Guillemette answer, after you disable the Control:
((Control)this.tabPage).Enabled = false;
...you may then handle the TabControl's Selecting event as:
private void tabControl_Selecting(object sender, TabControlCancelEventArgs e)
{
e.Cancel = !((Control)e.TabPage).Enabled;
}
This will remove the tab page, but you'll need to re-add it when you need it:
tabControl1.Controls.Remove(tabPage2);
If you are going to need it later, you might want to store it in a temporary tabpage before the remove and then re-add it when needed.
The only way is to catch the Selecting event and prevent a tab from being activated.
The most tricky way is to make its parent equals null (make the tab alone without parent):
tabPage.Parent = null;
And when you want to return it back (will return it back at the end of pages collection) :
tabPage.Parent = tabControl;
And if you want to return it back in a specific location among the pages you can use :
tabControl.TabPages.Insert(indexLocationYouWant, tabPage);
I had to handle this a while back. I removed the Tab from the TabPages collection (I think that's it) and added it back in when the conditions changed. But that was only in Winforms where I could keep the tab around until I needed it again.
I've removed tab pages in the past to prevent the user from clicking them. This probably isn't the best solution though because they may need to see that the tab page exists.
Using events, and the properties of the tab control you can enable/disable what you want when you want. I used one bool that is available to all methods in the mdi child form class where the tabControl is being used.
Remember the selecting event fires every time any tab is clicked. For large numbers of tabs a "CASE" might be easier to use than a bunch of ifs.
public partial class Form2 : Form
{
bool formComplete = false;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
formComplete = true;
tabControl1.SelectTab(1);
}
private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (tabControl1.SelectedTab == tabControl1.TabPages[1])
{
tabControl1.Enabled = false;
if (formComplete)
{
MessageBox.Show("You will be taken to next tab");
tabControl1.SelectTab(1);
}
else
{
MessageBox.Show("Try completing form first");
tabControl1.SelectTab(0);
}
tabControl1.Enabled = true;
}
}
}
I've solved this problem like this:
I've got 3 tabs and I want to keep user at the first tab if he didnt log in,
so on the SelectingEvent of TabControl I wrote
if (condition) { TabControl.Deselect("2ndPage"); TabControl.Deselect("3dPage"); }
The user cannot click on tabs to navigate, but they can use the two buttons (Next and Back). The user cannot continue to the next if the //conditions are no met.
private int currentTab = 0;
private void frmOneTimeEntry_Load(object sender, EventArgs e)
{
tabMenu.Selecting += new TabControlCancelEventHandler(tabMenu_Selecting);
}
private void tabMenu_Selecting(object sender, TabControlCancelEventArgs e)
{
tabMenu.SelectTab(currentTab);
}
private void btnNextStep_Click(object sender, EventArgs e)
{
switch(tabMenu.SelectedIndex)
{
case 0:
//if conditions met GoTo
case 2:
//if conditions met GoTo
case n:
//if conditions met GoTo
{
CanLeaveTab:
currentTab++;
tabMenu.SelectTab(tabMenu.SelectedIndex + 1);
if (tabMenu.SelectedIndex == 3)
btnNextStep.Enabled = false;
if (btnBackStep.Enabled == false)
btnBackStep.Enabled = true;
CannotLeaveTab:
;
}
private void btnBackStep_Click(object sender, EventArgs e)
{
currentTab--;
tabMenu.SelectTab(tabMenu.SelectedIndex - 1);
if (tabMenu.SelectedIndex == 0)
btnBackStep.Enabled = false;
if (btnNextStep.Enabled == false)
btnNextStep.Enabled = true;
}
tabControl.TabPages.Remove(tabPage1);
This is an old question, but someone may benefit from my addition. I needed a TabControl that would show hidden tabs successively (after an action was performed on the current tab). So, I made a quick class to inherit from and called HideSuccessive() on Load:
public class RevealingTabControl : TabControl
{
private Action _showNextRequested = delegate { };
public void HideSuccessive()
{
var tabPages = this.TabPages.Cast<TabPage>().Skip(1);
var queue = new ConcurrentQueue<TabPage>(tabPages);
tabPages.ToList().ForEach(t => t.Parent = null);
_showNextRequested = () =>
{
if (queue.TryDequeue(out TabPage tabPage))
tabPage.Parent = this;
};
}
public void ShowNext() => _showNextRequested();
}
There is the XtraTabPage.PageEnabled property allowing you to disable certain pages.
Here the solution that i implement:
private void switchTapPage(TabPage tabPage)
{
foreach(TabPage page in tabControl1.TabPages)
{
tabControl1.TabPages.Remove(page);
}
tabControl1.TabPages.Add(tabPage);
}
Basically, i just call this method sending the tabPage that i currently need to show, the method will remove all the tabPages on the tabControl and after that it will just add the one that i sent it.
So the rest of the tabHeaders will not shown and they will be inaccessible, because they dont even exists in the tabControl.
I took the idea from the #stormenet answer.
You can do it through the tabpages: tabPage1.Hide(), tabPage2.Show() etc.
In the form load event if we write this.tabpage.PageEnabled = false, the tabpage will be disabled.
Assume that you have these controls:
TabControl with name tcExemple.
TabPages with names tpEx1 and tpEx2.
Try it:
Set DrawMode of your TabPage to OwnerDrawFixed;
After InitializeComponent(), make sure that tpEx2 is not enable by adding this code:
((Control)tcExemple.TabPages["tpEx2").Enabled = false;
Add to Selection tcExemple event the code below:
private void tcExemple_Selecting(object sender, TabControlCancelEventArgs e)
{
if (!((Control)e.TabPage).Enabled)
{
e.Cancel = true;
}
}
Attach to DrawItem event of tcExemple this code:
private void tcExemple_DrawItem(object sender, DrawItemEventArgs e)
{
TabPage page = tcExemple.TabPages[e.Index];
if (!((Control)page).Enabled)
{
using (SolidBrush brush = new SolidBrush(SystemColors.GrayText))
{
e.Graphics.DrawString(page.Text, page.Font, brush, e.Bounds);
}
}
else
{
using (SolidBrush brush = new SolidBrush(page.ForeColor))
{
e.Graphics.DrawString(page.Text, page.Font, brush, e.Bounds);
}
}
}
It will make the second tab non-clickable.
I could not find an appropriate answer to the question. There looks to be no solution to disable the specific tab. What I did is to pass the specific tab to a variable and in SelectedIndexChanged event put it back to SelectedIndex:
//variable for your specific tab
int _TAB = 0;
//here you specify your tab that you want to expose
_TAB = 1;
tabHolder.SelectedIndex = _TAB;
private void tabHolder_SelectedIndexChanged(object sender, EventArgs e)
{
if (_TAB != 0) tabHolder.SelectedIndex = _TAB;
}
So, you don't actually disable the tab, but when another tab is clicked it always returns you to the selected tab.
in C# 7.0, there is a new feature called Pattern Matching. You can disable all tabs via Type Pattern.
foreach (Control control in Controls)
{
// the is expression tests the variable and
// assigned it to a new appropriate variable type
if (control is TabControl tabs)
{
tabs.Enabled = false;
}
}
Use:
tabControl1.TabPages[1].Enabled = false;
By writing this code, the tab page won't be completely disabled (not being able to select), but its internal content will be disabled which I think satisfy your needs.
The solution is very simple.
Remove/comment this line
this.tabControl.Controls.Add(this.YourTabName);
in IntializeComponent() method in MainForm.cs
MyTabControl.SelectedTab.Enabled = false;