AutoTab to Next TabPage in TabControl - c#

C# .Net fw 3.5, in winform in TabControl,
when the user tab out of the last control on a TabPage, then focus should moves to the next page, and focuses the first control in that page, how can i do it?
this is necessary for me because, in a master entry form, there is some compulsory questions which is placed out side of tabcontrol, and some controls which is not necessary all in tabcontrol,
if user visiting each control sequentially then focus should automatically move to next pages, if user want to fill only neccessory infos, then he can submit by clicking save button.
is any suggestion about this.

your question is not accurate
"C# .Net fw 3.5, in winform in TabControl, when the user tab out of the last control on a TabPage, then focus should moves to the next page, and focuses the first control in that page?"
is this a statement or question. I didnt understand. And what is the goal you need ?
If you want the user consequently visit the controls inside the consequent tabs by pressing tab key you can do it by keypressed event in tab control. In the keypressed event you can change the tab programatically.
hope it helps.
The code should be something like this.
Generate keypress event for your tabcontrol and monitor the press of TAB key.
private void tabControl1_KeyPress(object sender, KeyPressEventArgs e)
{
if(e.ToString().Equals("TAB") // I dont know what tab key returns. But is hould be something like this
{
tabControl1.SelectedTab = tabControl1.TabPages[1] ;
// now tabpage 2 has the focus
// You can also focus any control you want in here as follows:
tabControl1.TabPages[1].Control["control key"].Focus();
}
}
hope its clear enough

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
namespace CSBSSWControls
{
// Class inhertis TabControl
public class bssTabControl : TabControl
{
private bool AutoTab_;
[DefaultValue(false)]
public bool AutoTab { get { return AutoTab_; } set { AutoTab_ = value; } }
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
//property which determines auto change tabpages
if (AutoTab)
{
switch (keyData)
{
case Keys.Tab | Keys.Shift:
{
return SetNextTab(false);
}
case Keys.Tab:
{
return SetNextTab(true);
}
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
private bool SetNextTab(bool Forward)
{
// getting cuurent active control
ContainerControl CC = this.FindForm();
Control ActC = null;
while (CC != null)
{
ActC = CC.ActiveControl;
CC = ActC as ContainerControl;
}
//checking, current control should not be tabcontrol or tabpage
if (ActC != null && !(ActC is TabPage) && !(ActC is bssTabControl))
{
//getting current controls next control if it is tab page then current control is surely that last control on that tab page
//if shift+tab pressed then checked its previous control, if it is tab page then current control is first control on the current tab page.
TabPage NC = ActC.FindForm().GetNextControl(ActC, Forward) as TabPage;
if (NC != null)
if (this.TabPages.Contains(NC))
if (Forward)
{
//selecting next tab page
this.SelectedTab = NC;
return true;
}
else
{
if (this.TabPages.IndexOf(NC) > 0)
{
//selecting pervious tab page
this.SelectedIndex = this.TabPages.IndexOf(NC) - 1;
return true;
}
}
}
return false;
}
}
}

Related

How to use ctrl key + mouse click to select multiple controls?

Probably this question has already an answer here but I was not able to find it..
I have a tabControl with a flowlayoutpanel in each tab page where I can add controls at run time. I can rearrange them, move them across tab pages.. How can I select multiple controls to be able to move them around using ctrl key + mouse click?
This is my drag event so far:
private void control_DragDrop(object sender, DragEventArgs e)
{
Control target = new Control();
target.Parent = sender as Control;
if (target != null)
{
int targetIndex = FindCSTIndex(target.Parent);
if (targetIndex != -1)
{
string cst_ctrl = typeof(CustomControl).FullName;
if (e.Data.GetDataPresent(cst_ctrl))
{
Button source = new Button();
source.Parent = e.Data.GetData(cst_ctrl) as CustomControl;
if (targetIndex != -1)
fl_panel = (FlowLayoutPanel)tabControl1.SelectedTab.Controls[0];
if (source.Parent.Parent.Name == target.Parent.Parent.Parent.Name)
{
this.fl_panel.Controls.SetChildIndex(source.Parent, targetIndex);
}
else
{
target.Parent.Parent.Parent.Controls.Add(source.Parent);
this.fl_panel.Controls.SetChildIndex(source.Parent, targetIndex);
}
}
}
}
}
private int FindCSTIndex(Control cst_ctr)
{
fl_panel = (FlowLayoutPanel)tabControl1.SelectedTab.Controls[0];
for (int i = 0; i < this.fl_panel.Controls.Count; i++)
{
CustomControl target = this.fl_panel.Controls[i] as CustomControl;
if (cst_ctr.Parent == target)
return i;
}
return -1;
}
This is not an easy, nor a common task. But surely doable and depending on preconditions could become trivial without need to spend multi-man-year effort on it ^^.
You have many options:
controls support selection;
container control support children controls selection;
overlay.
Handling selection is pretty easy: have a dictionary (or a control property, possibly using Tag) to store if control is selected or not, show selection somehow, when control is Ctrl-clicked invert selection. You can even provide Shift-key selection.
As #Hans Passant commented, you can use overlay window (invisible window on top of everything) to draw selection reticle there as well as handle selection and dragging itself. Or it could be a custom control with property IsSelected, setting which will draw something (border?) to indicate selection.
Easiest option would be to create SelectionPanel control, which can host any other controls inside, has IsSelected indication and is draggable. When children is added subscribe to MouseUp/MouseDown events or you can only allow to drag if special area of SelectionPanel is clicked. To example, you could have option Enable dragging in your software, when set all SelectionPanels will display special area (header?) which you can drag or Ctrl-click.

WinForms & Infragistics controls readonly property does not work for clicked control

I wrote this code to make all controls readonly.
makeReadOnly(Control control, bool bIsReadOnly)
{
for(int i=0; i< control.Controls.Count; i++)
{
if(control.Controls[i].Controls.Count > 0)
{
makeReadOnly(control.Controls[i], bIsReadOnly);
}
else if(control.Controls[i].GetType() == typeof(UltraTextEditor))
{
(control.Controls[i] as UltraTextEditor).ReadOnly = bIsReadOnly;
}
else if(control.Controls[i].GetType() == typeof(UltraNumericEditor))
{
(control.Controls[i] as UltraNumericEditor).ReadOnly = bIsReadOnly;
}
else if(control.Controls[i].GetType() == typeof(ListBox))
{
(control.Controls[i] as ListBox).Enable = !bIsReadOnly;
}
}
}
It works but if user clicks one control such as a textbox, then click edit button(call makeReadOnly function). Function does not work for the clicked textbox. (It works for the other controls only).
Private void EditButton_Click()
{
foreach(Controls control in this.controls)
{
makeReadOnly(control, false);
}
}
"this" represents parent form."EditButton_Click()" is button event.
Why it is not working for the clicked ones?
How can I solve this problem?
I think, I found the answer. The problem is in Infragistics controls. When a user clicks an UltraTextEditor or UltraComboEditor controls, Infragistics changes its type to something like "EmbeddableUIText..." and its parent type becomes UltraTextEditor or UltraComboEditor. So, I have to check this types or controls' parent types to solve it.

i want to check User Control is dock or not after adding user control to Form

i have make user control and inside that user control takes two buttons name dock and close respectively .
now i want to dock my user control to left when i clicks button dock and close my user control when i clicks button close..
now it works fine.....
but when i add my usercontrol to the toolbox by taking choose items....
then drag and drop my user control to form...
now i have chk on form move event if user control is dock or not...
(i am trying to use by making object of user control but doesnt helps.....)
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
Container_User_Control.Container1 obj = new Container_User_Control.Container1();
if (obj.Dock != DockStyle.Left)
{
obj.visible=false;
}
else
{
obj.visible=true;
}
}
Thanks in advanced....
I have no idea why you are using a Mouse_Move event but if I understood your question right then:
When you drag your UserControl from the toolbox to the form, an instance of the usercontrol is created in the form designer code. Something like Container_User_Control1, so instead of using:
Container_User_Control.Container1 obj = new Container_User_Control.Container1();
if (obj.Dock != DockStyle.Left)
{
MessageBox.Show("none");
}
else
{
MessageBox.Show("left");
}
use:
if (Container_User_Control1.Dock != DockStyle.Left)
{
MessageBox.Show("none");
}
else
{
MessageBox.Show("left");
}

Set Focus to Any Control After PostBack

First I have 3 TextBoxes, a DropDownList, a CheckBox, and 2 LinkButtons in a table. The TextBoxes and DropDownList must do an AutoPostBack because there are some calculations being done on the server side which called by OnTextChanged.
My issue here is that after the content of any Control (which requires a PostBack) changes and you attempt to move focus to any other Control on the page (whether it be tabbing or using the mouse to click on any other Control) the focus does not move to the next Control or the Control you clicked.
I tried using a method which finds the current Control and based on the TabIndex, adds 1 which moves the focus to the next control. The problem here is that it does not allow for focus to be set on any other Control other than that one with the next TabIndex. To better explain here is an example of the situation.
Example: I have TextBox1, TextBox2, and TextBox3. I change the content in TextBox2 then want to move backwards to TextBox1. When I click in TextBox1 the focus is set to TextBox3 since the code is using the order of the TabIndex. ** A key factor here is that TextBox1 DOES get focus before the server side code fires but then loses focus and sets it on TextBox3 **
To me, it seems like the only way this can be accomplished would be to add a function on the client side which finds the Control with focus before the PostBack occurs, then reset the focus on that Control after the server side code completes. It does not seem like anything I do on the server side will work since the focus has already been lost when this occurs.
I have searched and searched but have not been able to find any solution to this particular issue, everything I have found deals with setting focus to the NEXT Control instead of the Control you want to have focus. Any help would be greatly appreciated. Thank you in advance.
Here is the code I am using to move to the next Control based on the TabIndex but this does not work in my situation.
protected void Page_Load(object sender, EventArgs e)
{
WebControl ctrl = GetPostBackControl() as WebControl;
if (ctrl != null && !SetNextFocus(Controls, ctrl.TabIndex + 1)) { ctrl.Focus(); }
}
public Control GetPostBackControl()
{
Control control = null;
string ctrlname = Request.Params.Get("__EVENTTARGET");
if (ctrlname != null && ctrlname != string.Empty)
{
control = FindControl(ctrlname);
control.Focus();
}
else
{
foreach (string ctl in Request.Form)
{
Control c = FindControl(ctl);
if (c is Button)
{
control = c;
break;
}
}
}
return control;
}
private bool SetNextFocus(ControlCollection controls, int tabIndex)
{
foreach (Control control in controls)
{
if (control.HasControls())
{
bool found = SetNextFocus(control.Controls, tabIndex);
if (found) { return true; }
}
WebControl webControl = control as WebControl;
if (webControl == null) { continue; }
if (webControl.TabIndex != tabIndex) { continue; }
webControl.Focus();
return true;
}
return false;
}
Try doing something like this to retain focus after postback:
/// <summary>
/// Overrides the OnLoad event moves the cursor to the appropriate control.
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
int currentTabIndex = 1;
WebControl postBackCtrl = (WebControl)GetControlThatCausedPostBack(Page);
foreach (WebControl ctrl in Panel1.Controls.OfType<WebControl>())
{
ctrl.TabIndex = (short)currentTabIndex;
if (postBackCtrl != null)
{
if (ctrl.TabIndex == postBackCtrl.TabIndex + 1)
ctrl.Focus();
}
currentTabIndex++;
}
}
/// <summary>
/// Retrieves the control that caused the postback.
/// </summary>
/// <param name="page"></param>
/// <returns></returns>
private Control GetControlThatCausedPostBack(Page page)
{
//initialize a control and set it to null
Control ctrl = null;
//get the event target name and find the control
string ctrlName = Page.Request.Params.Get("__EVENTTARGET");
if (!String.IsNullOrEmpty(ctrlName))
ctrl = page.FindControl(ctrlName);
//return the control to the calling method
return ctrl;
}
Thank you for the help, it did get me a little closer. The only thing that was preventing it from working correctly is that my page has some variables which are being carried over from other pages. When the page loads, the override is causing the page to break since it is unable to locate those controls. I was able to fix the issue by adding a HiddenField on the .aspx page and adding the following code to the onload() function:
if (document.getElementById("HiddenField1").value != "") {
var contr = document.getElementById(document.getElementById"HiddenField1").value);
contr.focus();
document.getElementById("HiddenField1").value = "";
}
as well as adding a new function which is called on each of the TextBoxes:
function tabFocus(e) {
document.getElementById("HiddenField1").value = e.id;
}
I ended up not having to make any changes in the code behind. Once again, thank you for the help!

C# WinForms Radio Buttons

I loaded 4 radios buttons and when I run the program and click on them, if i click one, and click another the other ones goes away. What if I wanted to ahve two radio buttons but they did different things?
Group the different choice sets in separate group boxes (or panels, or other container controls, but group boxes are probably what you're after).
MSDN:
Windows Forms RadioButton controls are designed to give users a choice among two or more settings, of which only one can be assigned to a procedure or object. For example, a group of RadioButton controls may display a choice of package carriers for an order, but only one of the carriers will be used. Therefore only one RadioButton at a time can be selected, even if it is a part of a functional group.
You group radio buttons by drawing them inside a container such as a Panel control, a GroupBox control, or a form.
This assumes you have four or more radio buttons on your form. If you have only two, say, and you want to allow the user the possibility of selecting both, use a set of checkboxes.
You should use GroupBox control.
All radio buttons in a GroupBox are mutually exclusive - put 2 radio buttons in one GroupBox, and the other 2 in another GroupBox.
If you don't like your container to be visible - use Panel control instead of GroupBox.
(Just drag and drop)
As you can probably guess, the upper one is a GroupBox, the lower one (which is invisble, but allows only one readioButton within it to be selected) is a panel.
HTH.
I like the concept of grouping RadioButtons in WPF. There is a property GroupName that specifies which RadioButton controls are mutually exclusive (http://msdn.microsoft.com/de-de/library/system.windows.controls.radiobutton.aspx).
So I wrote a derived class for WinForms that supports this feature:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Windows.Forms.VisualStyles;
using System.Drawing;
using System.ComponentModel;
namespace Use.your.own
{
public class AdvancedRadioButton : CheckBox
{
public enum Level { Parent, Form };
[Category("AdvancedRadioButton"),
Description("Gets or sets the level that specifies which RadioButton controls are affected."),
DefaultValue(Level.Parent)]
public Level GroupNameLevel { get; set; }
[Category("AdvancedRadioButton"),
Description("Gets or sets the name that specifies which RadioButton controls are mutually exclusive.")]
public string GroupName { get; set; }
protected override void OnCheckedChanged(EventArgs e)
{
base.OnCheckedChanged(e);
if (Checked)
{
var arbControls = (dynamic)null;
switch (GroupNameLevel)
{
case Level.Parent:
if (this.Parent != null)
arbControls = GetAll(this.Parent, typeof(AdvancedRadioButton));
break;
case Level.Form:
Form form = this.FindForm();
if (form != null)
arbControls = GetAll(this.FindForm(), typeof(AdvancedRadioButton));
break;
}
if (arbControls != null)
foreach (Control control in arbControls)
if (control != this &&
(control as AdvancedRadioButton).GroupName == this.GroupName)
(control as AdvancedRadioButton).Checked = false;
}
}
protected override void OnClick(EventArgs e)
{
if (!Checked)
base.OnClick(e);
}
protected override void OnPaint(PaintEventArgs pevent)
{
CheckBoxRenderer.DrawParentBackground(pevent.Graphics, pevent.ClipRectangle, this);
RadioButtonState radioButtonState;
if (Checked)
{
radioButtonState = RadioButtonState.CheckedNormal;
if (Focused)
radioButtonState = RadioButtonState.CheckedHot;
if (!Enabled)
radioButtonState = RadioButtonState.CheckedDisabled;
}
else
{
radioButtonState = RadioButtonState.UncheckedNormal;
if (Focused)
radioButtonState = RadioButtonState.UncheckedHot;
if (!Enabled)
radioButtonState = RadioButtonState.UncheckedDisabled;
}
Size glyphSize = RadioButtonRenderer.GetGlyphSize(pevent.Graphics, radioButtonState);
Rectangle rect = pevent.ClipRectangle;
rect.Width -= glyphSize.Width;
rect.Location = new Point(rect.Left + glyphSize.Width, rect.Top);
RadioButtonRenderer.DrawRadioButton(pevent.Graphics, new System.Drawing.Point(0, rect.Height / 2 - glyphSize.Height / 2), rect, this.Text, this.Font, this.Focused, radioButtonState);
}
private IEnumerable<Control> GetAll(Control control, Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAll(ctrl, type))
.Concat(controls)
.Where(c => c.GetType() == type);
}
}
}
Try placing similar options in a container, like GroupBox
Typically a group of radio buttons is used when only one option applies. If it is valid to select multiple options simultaneously, use Checkboxes instead.
Put all radio buttons into a group box.
Now, on all radio button Properties, set Auto Check to false.
Alternatively, you can set
radioButton1->AutoCheck = false;
Inside the radioButton1_Click function, handle as you needed. Example:
Void radioButton1_Click(Object^ sender, EventArgs^ e) {
radioButton1->Enabled = true;
radioButton2->Enabled = true;
radioButton3->Enabled = true;
radioButton1->Checked = true;
radioButton2->Checked = true;
radioButton3->Checked = true;
}
This should make those selected radio buttons to check.

Categories

Resources