Tab Control Events - c#

Is there a predefined event for Tab Controls, or maybe something custom I can develop, that will allow me to execute some logic on a control I've removed from that Tab Control's Control Collection, before it ACTUALLY gets removed from the tab control.
Context :
I have a tab control with tab pages. These tab pages load documents related to entries in a reference grid. Each time I select a row in the reference grid, a tab page with the corresponding document loaded gets added to my tab control. The Check column for that row in the grid also gets checked.
I want to be able to close a tab page in my tab control and be able to relate this closed tab page to its corresponding entry in the reference grid so i can uncheck that row.
I've tried browsing through all the possible events for tab control and found nothing suitable. The ControlRemoved event fires only AFTER my tabpage has closed and tab focus has automatically shifted to the next tab.... This is causing my controlremoved logic to fail and enter an infinite loop, trying to close ALL the available tabs instead of just this one, and throwing an invalid index exceptions when it's closed the final one.

You need to ensure that when you uncheck the item in your grid programmatically you do not update the tab control. Otherwise you always will run into an infinite loop causing the unwanted behavior.
You can achieve this by using a boolean flag. In the code-example below I haven't used the "real" event-handlers because I have no IDE at hand to test this at the moment, but rather replaced them by simple methods, so get the idea:
private bool suppressTabUpdate = false;
private void HandleGridCheckedOrUncheckedEvent()
{
if (suppressTabUpdate)
return;
// Insert logic here to create or remove the tab pages as required
}
private void HandleTabPageRemovedEvent()
{
suppressTabUpdate = true;
// Uncheck the item in the grid here
suppressTabUpdate = false;
}

I'm not sure if there's an exact event for you're looking for, but I have an alternative approach to propose.
It sounds to me that some of the UI code is too closely tied together. The grid and the tab control should not be talking to each other directly from the event handlers: that's what's causing the infinite loop (the events are "ping-ponging" back and forth).
Instead, I recommend that both the grid and the tab control be managed by another "component" (just a class, or a few methods in the existing form class) and that this component manage opening/closing tabs and modifying rows in the grid.
For example, when the user selects a row in the grid, don't modify the grid directly at all: instead, call a new method that does whatever needs to happen when a row is selected: check a checkbox, open a tab, etc. When a row no longer needs to be selected, don't change any selections directly: instead, call a new method that does whatever needs to happen when a row is not selected: uncheck a checkbox, close a tab, etc.

If you need a reference to your tab BEFORE it gets removed, there is one simple way to do it. Make CustomTabControl that inherits from TabControl and override its OnControlRemoved event.
If you have this:
public class CTabControl:TabControl
{
protected override void OnControlRemoved(ControlEventArgs e)
{
TabPage tp = e.Control as TabPage; // reference to tab page before it gets removed
base.OnControlRemoved(e);// gets removed here
}
}

Related

visual studio c# windows form checkBox

I need your help
as you can see from the screenshot image
I am trying to make a font dialog where i have:
a Label to test the change that will happen when I
click in the checkbox .as you can see I have 3 checkboxs.
the problem is that I cant make all the checkboxs work together
so the text changed to Bold,Italic and underline..help me please
.....
my Form design
i try to use if else statement
and also switch one and still I don't know how to do it that is why i m here
It's a bit unclear, as others have noted, but.. if you are wanting to combine the results of checked and/or unchecked options to display the results of a user's font styling choices?
THEN:
1.) double-click in your V.S. form designer one of the checkboxes, this will create an event handler in your form's C# code file. The function created will be something like checkbox1_checked(object sender, EventArgs e)
2.) In the event handler function that Visual Studio has scaffolded for you, write all the code necessary to consider the .Checked state of all checkbox controls and update your Label1 control appropriately (depending on your goal, this may require custom .NET painting logic that is too much for a beginner to think about)
3.) Go back to the other controls on your design surface, now select them.. keeping an eye on your lower-right 'Properties' panel, (make sure its switched to the 'events' tab - i.e. click the 'lightning bolt' button). Ensure that each of the other radio buttons that do not yet have an event handler get mapped: Find the row in the Properties panel that shows the word "click" (err.. 'checked' event?). When you click into the white space on the row, next to the word 'checked', it will allow you to select the pre-existing "checkbox1_checked" event handler than you created in step 1.
UPDATED:
4.) the end goal is to wire all checkbox controls to the same event handler function in your form's code-behind.. if you double-click each checkbox at design time.. you'll create separate event handlers.. but with some learning (or following my directions above) you can point them all to the same event handler.

how to shift controls from one tabpage to another at runtime c# Windows

I am using windows form. in which there is a tab control and three tab pages. in the first tab page i have a combobox. which loads some data from the database. I need to use this combobox in tabpage 2 and 3 . when the user select tabpage 2 the combobox should be visible. How can i achieve this.
There are 2 solutions that I can think of.
Move the combobox out of the tab control. Since all the tabs use the same combobox anyway then it serves a non-tab specific functionality. Design wise, this makes the most sense as you will avoid redundancy between the 3 comboboxes.
Create 3 separate comboboxes for each tab and make each combobox reference a same collection. Don't forget to update the selected item of all the 3 comboboxes once an item is chosen by the user. Also take not that this will require more code changes than the first solution.
Put your combobox on first tab. Then add an event handler to the SelectedIndexChanged event of your tab control and put this code in it:
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
tabControl1.SelectedTab.Controls.Add(this.comboBox1);
}
The Add will automatically remove it from the tab where it has been before. Of course you have to provide free space on all tabs where the combobox is located.
I tried, using the VB code: TabStrip1.SelectedTab.Controls.Add(*controlname*) to switch, but once it's off the original page and on to the new one, switching back to the original tab doesn't seem to work.
Just discovered that using *controlname*.BringToFront brings it on top again.

Trying to get object reference from FixedDocument via click

I am populating a FixedDocument as part of a reporting feature. I do not have control over the hows or whys of the approach, just that this is the approach used.
So I programmatically add rows to the page grid, add text controls to show the data, etc. It works.
Now I am trying to add support so that a user can click on an item in the report and I can open that item in an edit window. The only problem I am having is identifying what the user clicked on.
The FixedDocument captures the mouse clicks and ignored the mouseclick event added to the textbox.
As I add the textboxes, if I can keep track of the actual coordinates of the item added, then I can reference that via the code in the FixedDocument click event (since I have the coordinates or where the user clicked.)
What is an easy way for me to get an object reference or information about the item over which the user clicked?
I tried searching , but nothing seemed to address this given all the search terms I could think of using.
Thanks
Try listening to PreviewMouseLeftButtonUp event of your fixed document. It exposes MouseButtonEventArgs parameter from where you can lookup OriginalSource and compare it with your textbox and perform the necessary action.
You can choose to use any other Preview prefixed event for your benefit wherever you have a similar need.

C# WinForm press tabs and it jumps all over the place

I have a WinForm program. In one screen it has several ComboBoxes, TextBoxes, and Buttons. How can I make it so that when the user presses tab, it will go through the fields in sequential order. Meaning from top to bottom? Or we can say "In my defined order"? So, for example, it starts with TextBox1, and then when the user presses Tab, it will go to the next TextBox, and when Tab is pressed again, will go to Button1, etc. etc.
Not sure if it’s possible, but for some reason pressing tab jumps all over the place. What defines the "tab"? what logic does it use to make it jump to the next field?
The TabIndex property of each control defines the tab order within a container (Form, GroupBox, Panel, etc). If you are working in the Visual Studio Designer, you can use the View --> Tab Order menu item to view/edit the tab sequence.
Each control has a property called TabIndex. When a user presses the Tab key, Windows cycles through each control in the order of the tab index. If two controls have the same TabIndex, they are selected in the order in which the controls were added to the Forms Controls collection.
It is also worth noting that if you have a control that can contain a group of controls within it's Controls collection (i.e. GroupBox), the tab processing engine will give tab focus to the parent control and then cycle through all of the internal controls, in their internal sorted order. This means that all child TabIndex values can be maintained independently of all other controls that are in the same collection as the parent control.
You need to use the TabIndex propert on the control. Be aware that according to the documentation, you must set the TabStop property to true in order for it to be included in the tab ordering.
You need to define the TabIndex of each control. There is a button in the designer toolbar to make it easier (I don't remember the name, but you should find it easily... it's probably something like "Tab Order"). Click this button, then click each control on the form in turn.
Each control has a property called "TabIndex". These will by default just be incrementing as you create items. You can set these manually.
Set the TabIndex: http://msdn.microsoft.com/en-us/library/aa984423%28v=vs.71%29.aspx
Please check out TabIndex property.

Windows Form App Handles Error

I have a windows form application that has two main panels: The one on the left is a narrow strip which has a series of radio buttons. The panel on the right houses a Tabcontrol, which has multiple Tabpages added to it which the user can select among along the top. Each of these tabpages themselves has about 7 DataGridViews added to it. Each DataGridView has about 5-6 columns of text, with a variable number of rows (10-500). The data added to it was done directly to the DGV itself, ie using the DGV.Rows.Add() method, passing an object array, not via a datasource.
When a user selects a different tab page, the datagridview that gets shown is dependent on the radiobutton that is selected on the left. I accomplish this by handling the SelectedIndexChange event of the tabcontrol and each of the radiobutton's CheckedChange event.
Within the SelectedIndexChange event of the tabcontrol, I programmatically checked the currently selected radioButton. Then within the radiobutton's CheckedChange event, I iterate through all of the DataGridViews on the TabControl's selectedTab and hide all those that don't match the one corresponding to the selected radiobutton.
My issue is everytime the user starts changing among a lot of tabs, or tries to view a DGV that has many rows, the program would throw the following error:
System.ComponentModel.Win32Exxception: Error creating window handle.
Does anyone know what would cause the above error? My initial suspicion was that when I change to a different tabpage, the DGV on the original tabpage i was on was still in memory, but when I try calling .Dispose() on it, the DGV just disappears. It may be I am missing something fundamental here.
The problem is that you are probably trying to show a disposed DataGridView.
Do not dispose any Control in your form unless you are previously removing it from the appropiate Container.Controls collection (because you do not need it anymore and/or you plan adding a new one in its place). Otherwise dispose any controls when closing and disposing the Form that contains them if necessary.
In order to show the proper DataGridView depending on selected tab and user options use the Visible property or dynamically add and remove the needed controls to the container's Controls collection (in this case TabPage.Controls.
If its not that then maybe you have a "control leak" (probably event handler holding the object) and you are exceeding the windows handle limit for any given application (10.000 I think it is).

Categories