Radiobuttons in different group boxes - vb.net

Quite a silly question, but still annoying.
The thing is that i have two group boxes where the titles have radiobuttons covering the group box titles.
Something like
(x) I want pizza
*Pizza stuff*
( ) I want Hamburger
*Hamburger stuff*
Since they're now in different group boxes, they can both be selected.
Is there a way to set/force the radiobuttons to be in the same "group"? Like in HTML where you set
name="WhatToEat" value="Pizza" for the first value and then
name="WhatToEat" value="Hamburger"
Or can i set the title for the groupbox to behave like a radio button or something?
Of course i can have the radio button outside the grop boxes, but i think having the titles as radiobuttons just makes the most sense and looks nicer.

If you have all your RadioButtons on a form. You can use a RadioButton variable to mark what is currently checked. Every time user checks a RadioButton, if it's not the currently checked RadioButton, make the currently checked RadioButton unchecked, and set the currently checked RadioButton to that RadioButton.
Here is my code:
public Form1(){
InitializeComponents();
currentChecked = radioButton1;
}
//Suppose the initially checked radio is radioButton1
RadioButton currentChecked;
//This is the CheckedChanged event handler used for all the radiobuttons
private void radioButtonChecked(object sender, EventArgs e)
{
RadioButton r = (RadioButton)sender;
if (r != currentChecked)
{
currentChecked.Checked = false;
currentChecked = r;
}
}
My code is much simpler without using any loop. It costs the additional currentChecked but it's not much.
Hope it helps!

No, it have to in one group ..
But for that case you can control in checked_change event
Private Sub RadioButton2_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButton2.CheckedChanged
RadioButton1.Checked = Not RadioButton2.Checked
End Sub
Private Sub RadioButton1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButton1.CheckedChanged
RadioButton2.Checked = Not RadioButton1.Checked
End Sub

Just move them to the Form at run-time. Use PointToScreen() and PointToClient() to keep them in the same position as you placed them at desing-time. So you'd replace "RadioButton1", "RadioButton2", and "RadioButton3" with your title RadioButtons:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim RadioTitles() As RadioButton = {RadioButton1, RadioButton2, RadioButton3}
For Each rb As RadioButton In RadioTitles
Dim pt As Point = Me.PointToClient(rb.PointToScreen(New Point(0, 0)))
Me.Controls.Add(rb)
rb.Location = pt
rb.BringToFront()
Next
End Sub
*You could put a value into the Tag() property of each RadioButton that should be the "title" and then search for those instead of hard-coding them into the array. Or maybe you could name them a certain way.
EDIT: You could make the "title" RadioButtons enable/disable their associated GroupBoxes when they are checked like this:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim RadioTitles() As RadioButton = {RadioButton1, RadioButton2, RadioButton3}
For Each rb As RadioButton In RadioTitles
rb.Parent.Enabled = False
rb.Tag = rb.Parent
AddHandler rb.CheckedChanged, AddressOf TitleRadioButtons_CheckedChanged
Dim pt As Point = Me.PointToClient(rb.PointToScreen(New Point(0, 0)))
Me.Controls.Add(rb)
rb.Location = pt
rb.BringToFront()
Next
End Sub
Private Sub TitleRadioButtons_CheckedChanged(sender As Object, e As System.EventArgs)
Dim rb As RadioButton = DirectCast(sender, RadioButton)
If Not IsNothing(rb.Tag) AndAlso TypeOf rb.Tag Is Control Then
Dim ctl As Control = DirectCast(rb.Tag, Control)
ctl.Enabled = rb.Checked
End If
End Sub

Unfortunately, that's not how radio buttons work.
As I'm sure you're aware, radio buttons get their grouping from containers. To my knowledge, if you want to be able to accomplish what you're asking, you'll probably need to code a custom solution. For instance, you could place an event handler on each radio button to fire off the same event to uncheck other boxes, e.g.
radioButton1.CheckedChanged += anyRadioButton_CheckedChanged;
radioButton2.CheckedChanged += anyRadioButton_CheckedChanged;
radioButton3.CheckedChanged += anyRadioButton_CheckedChanged;
...
private void anyRadioButton_CheckedChanged(object sender, EventArgs e)
{
foreach (var control in this.Controls)
{
if(control is GroupBox)
{
foreach (var childControl in ((GroupBox)control).Controls)
{
if (childControl is RadioButton && childControl != sender)
{
((RadioButton)childControl).Checked = false;
}
}
}
}
}

You can set text of the GroupBox to empty string and put RadioButton over it. The trick is to put it on form actually but move it the way it looks like part of GroupBox. But this is sufficient only if your group boxes are static and won't be moved. Otherwise it is better to use solution which #matzone proposed. But even in that case you can put all radio buttons in collection in your code and use the only event handler for all of them. Something like
private List<RadioButton> radioButtons;
public YourFormConstructor()
{
InitializeComponent();
radioButtons.Add(radio1);
radioButtons.Add(radio2);
radioButtons.Add(radio3);
foreach (var radio in radioButtons)
radio.CheckedChanged += RadioCheckedChanged;
}
private void CheckedChanged(object sender, EventArgs e)
{
var thisRadio = sender as RadioButton;
if (!thisRadio.Checked)
return;
foreach (var radio in radioButtons)
if (radio != thisRadio)
radio.Checked = false;
}

Related

How to make a user select an image and save the image as a variable?

I am trying to create a VB.net form where the user can click on a button and it is associated with a specific image and when the user clicks the image and then clicks select it will add it to a variable.
If you need more information please let me know (this is the image of my form)
I wanted to know:
how to assign an image to a button ( so when you click it, it means that the user wants that image) I am not sure if my method is correct
how to assign the image that was selected to a variable (so that once the variable is called it will output the image)
and how to end the form once the image is selected. (once use clicks the select button it should end the form, or if the user clicks cancel it should end the form).
Public Class Form1
Private Property SelectedPictureBox() As Image
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Controls.OfType(Of ButtonPictureBox).ToList().ForEach(
Sub(box)
AddHandler box.Click, AddressOf AllButton_Click
End Sub)
End Sub
Private Sub AllButton_Click(sender As Object, e As EventArgs)
SelectedPictureBox = CType(sender, ButtonPictureBox).PictureBox
End Sub
Private Sub GetBtnSelect_Click(sender As Object, e As EventArgs) Handles GetBtnSelect.Click
If SelectedPictureBox IsNot Nothing Then
MessageBox.Show(SelectedPictureBox.Name)
Else
MessageBox.Show("Please select an image")
End If
End Sub
Private Sub BtnTropicalFloral_Click(sender As Object, e As EventArgs) Handles BtnTropicalFloral.Click
SelectedPictureBox = PictureBoxTropicalFloral.Image
End Sub
Private Sub BtnLightGeode_Click(sender As Object, e As EventArgs) Handles BtnLightGeode.Click
SelectedPictureBox = PictureBoxLightGeode.Image
End Sub
Private Sub BtnStripes_Click(sender As Object, e As EventArgs) Handles BtnStripes.Click
SelectedPictureBox = PictureBoxStripes.Image
End Sub
Private Sub BtnAuroraBorealis_Click(sender As Object, e As EventArgs) Handles BtnAuroraBorealis.Click
SelectedPictureBox = PictureBoxAuroraBorealis.Image
End Sub
Private Sub BtnDiagonals_Click(sender As Object, e As EventArgs) Handles BtnDiagonals.Click
SelectedPictureBox = PictureBoxDiagonals.Image
End Sub
Private Sub BtnComb_Click(sender As Object, e As EventArgs) Handles BtnComb.Click
SelectedPictureBox = PictureBoxComb.Image
End Sub
Private Sub BtnMountain_Click(sender As Object, e As EventArgs) Handles BtnMountain.Click
SelectedPictureBox = PictureBoxMountain.Image
End Sub
Private Sub BtnLandscape_Click(sender As Object, e As EventArgs) Handles BtnLandscape.Click
SelectedPictureBox = PictureBoxLandscape.Image
End Sub
Private Sub BtnGradient_Click(sender As Object, e As EventArgs) Handles BtnGradient.Click
SelectedPictureBox = PictureBoxGradient.Image
End Sub
Private Sub BtnAbstract_Click(sender As Object, e As EventArgs) Handles BtnAbstract.Click
SelectedPictureBox = PictureBoxAbstract.Image
End Sub
Private Sub BtnGeode_Click(sender As Object, e As EventArgs) Handles BtnGeode.Click
SelectedPictureBox = PictureBoxGeode.Image
End Sub
End Class
My VB is a bit rusty, so I'll have to give the answer in C#. I'm sure you'll get the gist, and will be able to translate it into VB.
First of all: whenever you see that you are repeating things, for instance by copy-paste, you should stop, and rethink your design: maybe it would be better to create a method for this, or an object.
All your PictureBox/Button combinations have some common behavior. This means that you should think of creating a class for it.
In your case, you have the combination of a Button and a PictureBox. You want to be able to set and get an Image. The PictureBox will show this image. Finally you want to be notified if the operator clicks the Button.
In the event handler of this Notification you want to know which pictureBox/Button combination sent the event. You get the image from this combination and close the form.
In WinForms, whenever you want to have a class that is a combination of several controls, you make a UserControl.
In Visual Studio, in the solution control, right click on the project (not the solution!) and select: Add new Item. Select to add a new User Control. Think of a proper name, I'll call this ImageSelectionControl
Use the visual studio designer to give ImageSelectionControl the proper size. Add a PictureBox and a Button. Also use the visual studio designer to add an EventHandler for if the operator clicks the button.
In the code of the User Control add the property to Set / Get an Image. The Image that you set will be displayed in the PictureBox; the Image that you get is the image that is displayed in the PictureBox.
Here comes the first chunk of C#:
public Image Image
{
get => this.pictureBox1.Image;
set => this.pictureBox1.Image = value;
}
I think in VB this will be very similar.
Now you want that users of your control (= software, not humanoids) get notified that the operator selects an image. Officially, you even want to hide how the operator selected this image: all you want to say: "Hey, the operator selected my image!"
Normally you would do this using an event:
The 2nd piece of C#:
public event EventHandler ImageSelected;
The event won't have any data. It will only say: "Hey, the operator selected my image!". The event event handler will have to find out which user control raised the event, and fetch the image.
Ok, raise the event:
private void OnImageSelected()
{
this.ImageSelected?.Invoke(this, EventArgs.Empty);
}
It will be a bit more difficult to translate this into VB. What it does, it checks if there is at least one person who wants my events. If so it raises the event. with two parameters: the sender (which is me), and no parameters. Later we will see how the receiver of the event works.
Finally: if the operator clicks the button, he indicates that he wants to select the image in the user control, and thus OnImageSelected needs to be called
private void ButtonSelect_Clicked(object sender, EventArgs e)
{
this.OnImageSelected();
}
We've finished creating the UserControl. After Compilation you will find it in visual studio designer toolbox.
So we'll go to the form that will have to display the eleven PictureBox-Button combinations. Let's call this form: ImageSelectionForm.
Using Visual Studio Designer, add 11 ImageSelectionControls. If you know already at design time which control will show which image, you can do this in the designer, similarly to how you set the text or the background of a button.
If you only know at run-time which control should show which image, consider to add a method, for instance if you want to load it from file:
void ShowImage(ImageSelectionControl imageSelectionControl, string imageFileName)
{
Image image = this.LoadImageFromFile(imageFileName);
this.imageSelectionControl.Image = image;
}
Or maybe you have a different method to decide which ImageSelectionControl should displaye which image. I guess you get the gist.
Almost done. ImageSelectionForm needs to be notified about the selected image, so just like you would do with a button, you need to subscribe to event ImageSelected.
In the constructor or ImageSelectionForm, subscribe to the events:
private ImageSelectionForm()
{
InitializeComponent();
// subscribe to events
this.controlBlueGeod.ImageSelected += this.ImageSelected;
this.controlAbstract.ImageSelected += this.ImageSelected;
...
}
Of course, you can put all ImageSelectionControls in one list and use foreach to subscribe (that is too much VB for me, no idea how to do this)
The event handler:
void ImageSelected(object sender, EventArgs e)
{
// we know that the sender is the one that holds the selected images:
ImageSelectionControl imageSelectionControl = (ImageSelectionControl)sender;
We will be closiing the form very soon, so we will have to remember this selected image somewhere in a property:
public Image SelectedImage {get; set;}
So continuing the event handler:
this.SelectedImage = imageSelectionControl.Image;
this.DialogResult = DialogResult.OK;
this.Close();
}
So the selected image is saved. The dialog result is set to indicate that an image was selected, not cancel clicked. And the form is closed.
Showing the form and process the selected image
The form that has to show ImageSelectionForm has a procedure:
private void ShowImageSelectionForm()
{
using (ImageSelectionForm dialog = new ImageSelectionForm())
{
// show the dialog and process the result:
DialogResult dlgResult = dialog.ShowDialog(this);
if (dlgResult == DialogResult.OK)
{
this.ProcessSelectedImage(dialog.SelectedImage);
}
else
{
// TODO: process cancel
}
}
}
There is one memory leak: if you created a lot of images, all images need to be Disposed after usage. Best is to by overriding Component.Dispos(bool)
ImageSelectionControl:
protected override Dispose (bool disposing)
{
if (disposing && this.Image != null)
{
this.Image.Dispose();
}
}
ImageSelectionForm:
protected override Dispose (bool disposing)
{
if (disposing)
{
this.controlBlueGeod.Dispose();
this.controlAbstract.Dispose();
...
} ​
​}
This is quite a nuisance for 11 controls. Therefore quite often a Form or a UserControl has a System.ComponentModel.IContainer components. If you add your ImageSelectionControls to this container, then the ImageSelectionControls will be automatically disposed when ImageSelectionForm is disposed.
​
You have two Controls that work together to allow users to preview and select one or more Images in the UI. When you have this kind of scenario, build a UserControl that contains all the required UI elements and the logic used perform this action.
To build this UserControl:
Open the Project menu and select Add User Control...
Right away, set (in this order):
AutoScaleMode = Dpi
Font = Segoe UI, 9pt
BackColor = Color.Transparent
Set a Size that you think is the minimum required to show an Image and a Button
When you have found the right size, set also the MinimumSize to this value
Add a Button to the UC, configure it as needed, set its Width as the Width of the UC minus 4 pixels. Position the Button at the bottom of UC, 2 pixels to the left and set Anchor = Bottom, Left, Right
Add a PictureBox, same Width and Left location as the Button. Set the Height as required, then Anchor = Top, Bottom, Left, Right
Design completed. Build the Project.
Now, your UserControl needs to provide means to set an Image to the PictureBox and the Text of the Button.
You can add two Public Properties of Type Image and String that, when a value is assigned, set the PicureBox.Image property and the Button.Text property.
Also, when the Button is clicked, the UserControl needs to notify that the User has performed a selection, so whatever other code needs to do something with this information, will be able to act on it.
In an event-driven UI, you make your UC raise a public event that interested parties can subscribed to, to receive a notification that something happened.
You just need to define a Field of Type Event and give it a name. In this case, e.g.:
Public Event ImageSelection As EventHandler
When the Button is clicked, you raise the event:
RaiseEvent ImageSelection(Me, EventArgs.Empty)
The sample UserControl is named ImagePicker, the PictureBox is named picImage and the Button is btnSelectImage
Public Class ImagePicker
Public Event ImageSelection As EventHandler
Private m_Picture As Image = Nothing
Private m_Title As String
Public Property Picture As Image
Get
Return m_Picture
End Get
Set
m_Picture = Value
picImage.Image = m_Picture
End Set
End Property
Public Property Title As String
Get
Return m_Title
End Get
Set
m_Title = Value
btnSelectImage.Text = m_Title
End Set
End Property
Private Sub btnSelectImage_Click(sender As Object, e As EventArgs) Handles btnSelectImage.Click
RaiseEvent ImageSelection(Me, EventArgs.Empty)
End Sub
End Sub
In your Form (for example), you can the subscribe to this event to receive a notification that the User has selected the Image of one of your UserControls.
When the event is raised, the sender object is the UserControl that raised the event. You can then cast sender to your UserControl Type and read the Public Property that references the Image you have assigned to it.
In a Form, you can add some of your UserControls to a FlowLayoutPanel (in the example, named flpPreviews), which will take care of the layout of these Controls.
While adding the UserControls, you set their Public Properties and also subscribe to the Public event.
When the event is raised, cast sender to ImagePicker and read its public Picture property to get the reference of the Image selected:
Public Class SomeForm
Public Sub New()
InitializeComponent()
' Add three ImagePicker UserControls to a FlowLayoutPanel
For i As Integer = 0 To 2
Dim picker = New ImagePicker()
picker.Picture = [Some Image]
picker.Title = "Some Title"
' Subscribe to the event
AddHandler picker.ImageSelection, AddressOf ImageSelectionChanged
flpPreviews.Controls.Add(picker)
Next
End Sub
Private Property SelectedImage As Image
Private Sub ImageSelectionChanged(sender As Object, e As EventArgs)
SelectedImage = DirectCast(sender, ImagePicker).Picture
' Show the selected Image in a PictureBox, child of the Form
picSelected.Image = SelectedImage
End Sub
End Class

TabPage selection, move the Focus to the previous ActiveControl when a TabPage is reselected

I need some help to focus a particular control when a TabPage is revisited. I followed many other blogs, but I wasn't able to solve the problem myself.
I created the TabPages inside a MDIForm:
Public Sub Tab_Open(Of T As {Form, New})(name As String, NameofTab As String, Tabnumber As String)
Dim _formByName As New Dictionary(Of String, Form)
Dim Frm As Form = Nothing
If Not _formByName.TryGetValue(name, Frm) OrElse _formByName(name).IsDisposed Then
Frm = New T()
_formByName(name) = Frm
End If
Dim childTab As TabPage = New TabPage With {
.Name = NameofTab & " : " & Tabnumber,
.Text = NameofTab & " : " & Tabnumber,
.Tag = Frm.Name
}
Form1.tabForms.TabPages.Add(childTab)
Frm.TopLevel = False
Frm.FormBorderStyle = FormBorderStyle.None
Frm.Parent = Form1.tabForms.TabPages(Form1.tabForms.TabCount - 1)
Frm.Dock = DockStyle.Fill
Frm.Show()
Form1.tabForms.SelectedTab = childTab
Form1.tabForms.Visible = True
End Sub
Let's assume that in first TabPage the Focus was on a TextBox (with TabIndex = 4), now I may be click on the second TabPage.
After some calculations, when I select the previous TabPage, the Focus should be set to the TextBox with TabIndex = 4 again, but that's not happening.
I tried to create a Dictionary in the MDIForm as:
Public Tab_Last_Focus_info As New Dictionary(Of String, String())
and in SelectedIndexChanged I have this code:
Private Sub tabForms_SelectedIndexChanged(sender As Object, e As EventArgs) Handles tabForms.SelectedIndexChanged
If Tab_Last_Focus_info.ContainsKey(tabForms.SelectedTab.Name) Then
Dim FullTypeName1 As String = String.Format("{0}", Tab_Last_Focus_info.Item(tabForms.SelectedTab.Name))
Dim Indxval As String = String.Format("{1}", Tab_Last_Focus_info.Item(tabForms.SelectedTab.Name))
Dim FullTypeName As String = Application.ProductName & "." & FullTypeName1
Dim FormInstanceType As Type = Type.GetType(FullTypeName, True, True)
Dim frm As Form = CType(Activator.CreateInstance(FormInstanceType), Form)
Dim Focus_on As Integer = Integer.Parse(Indxval)
frm.Controls(Focus_on).Focus()
' Not working too =>
' frm.Controls(Focus_on).Select()
' Invisible or disabled control cannot be activated =>
' ActiveControl = frm.Controls(Focus_on) 'System.ArgumentException:
End If
End Sub
In the Form, which is opened via a Menu, I have this code for the Control that's focused:
Private Sub All_Got_Focus(sender As Object, e As EventArgs) Handles TB_ImageLoc.GotFocus, TB_CompWebsite.GotFocus,
TB_CompPinCD.GotFocus, TB_CompPAN.GotFocus, TB_CompName.GotFocus, TB_CompMobile.GotFocus,
TB_CompMD.GotFocus, TB_CompLL.GotFocus, TB_CompGSTIN.GotFocus, TB_CompFax.GotFocus, TB_CompEmail.GotFocus,
TB_CompCD.GotFocus, TB_CompAreaCity.GotFocus, RTB_CompADD.GotFocus, PB_Logo.GotFocus, DTP_CompEst.GotFocus, DGV_CompList.GotFocus,
CHKB_CompIsRegTrans.GotFocus, CB_CompStateID.GotFocus, CB_CompDistrictID.GotFocus, But_Upd.GotFocus, But_SelectLogo.GotFocus,
But_Search.GotFocus, But_Reset.GotFocus, But_Refresh.GotFocus, But_GridSelect.GotFocus, But_Exit.GotFocus, But_Edit.GotFocus,
But_Del.GotFocus, But_Add.GotFocus
If Form1.Tab_Last_Focus_info.ContainsKey(Form1.tabForms.SelectedTab.Name) Then
Form1.Tab_Last_Focus_info.Remove(Form1.tabForms.SelectedTab.Name)
End If
Form1.Tab_Last_Focus_info.Add(Form1.tabForms.SelectedTab.Name, New String() {Me.Name, Me.ActiveControl.TabIndex})
End Sub
Now in TabIndexChange I'm getting a correct value from the Dictionary, but I'm not able to focus on the required tab.
Kindly help and let me know what I am missing or what need to taken care for this issue or please let me know any other better idea for the same.
First thing, a suggestion: test this code in a clean Project, where you have a MDIParent and one Form with a TabControl with 2 o more TabPages, containing different types of Controls. Test the functionality, then apply to the Project that is meant to use it.
You need to keep track of the selected Control in a TabPage - the current ActiveControl - switch to other TabPages, restore the previous ActiveControl in a TabPage when it's brought to front again.
The procedure is simple, implemented as follows:
To keep track of the current ActiveControl - the Control that has the Focus, you need to know when a Control becomes the ActiveControl. This Control of course must be child of a TabPage.
The ContainerControl class (the class from which Form derives) has a protected virtual method, UpdateDefaultButton(), that's overridden in the Form class. It's used to determine which child Button is activated when a User presses the Enter Key.
This method is called each time a new Control becomes the ActiveControl: overriding it, we can be informed when this happens, so we can check whether the new ActiveControl is one we're interested in, because it's child of a TabPage of our TabControl.
When the new ActiveControl is one we need to keep track of, we can store the reference of this Control and the Index of the TabPage it belongs to in a collection, so we can then use this reference, when the selected TabBage changes, to set it again as the ActiveControl in its TabPage.
Here, to store the state, I'm using a Dictionary(Of Integer, Control), where the Key is the Index of the TabPage and the Value is the reference of its ActiveControl.
When the TabControl.Selected event is raised - after a TabPage has been selected - we can lookup the Dictionary and restore the previous ActiveControl of that TabPage if one was stored.
► Here, BeginInvoke() is used to defer the action of setting the new ActiveControl, because this also causes a call to UpdateDefaultButton() and this method is called before the TabControl.Selected event handler completes.
Public Class SomeMdiChildForm
Private tabPagesActiveControl As New Dictionary(Of Integer, Control)()
' This method is called each time a Control becomes the ActiveControl
Protected Overrides Sub UpdateDefaultButton()
MyBase.UpdateDefaultButton()
If TypeOf ActiveControl.Parent Is TabPage Then
Dim tabPageIdx = CType(CType(ActiveControl.Parent, TabPage).Parent, TabControl).SelectedIndex
If tabPagesActiveControl.Count > 0 AndAlso tabPagesActiveControl.ContainsKey(tabPageIdx) Then
tabPagesActiveControl(tabPageIdx) = ActiveControl
Else
tabPagesActiveControl.Add(tabPageIdx, ActiveControl)
End If
End If
End Sub
Private Sub TabControl1_Selected(sender As Object, e As TabControlEventArgs) Handles TabControl1.Selected
Dim ctrl As Control = Nothing
If tabPagesActiveControl.TryGetValue(e.TabPageIndex, ctrl) Then
BeginInvoke(New Action(Sub() Me.ActiveControl = ctrl))
End If
End Sub
End Class
C# Version:
(assume tabControl1 is the name of the TabControl instance)
public partial class SomeForm : Form
{
private Dictionary<int, Control> tabPagesActiveControl = new Dictionary<int, Control>();
// [...]
// This method is called each time a Control becomes the ActiveControl
protected override void UpdateDefaultButton()
{
base.UpdateDefaultButton();
if (ActiveControl.Parent is TabPage tp) {
var tabPageIdx = (tp.Parent as TabControl).SelectedIndex;
if (tabPagesActiveControl.Count > 0 && tabPagesActiveControl.ContainsKey(tabPageIdx)) {
tabPagesActiveControl[tabPageIdx] = ActiveControl;
}
else {
tabPagesActiveControl.Add(tabPageIdx, ActiveControl);
}
}
}
private void tabControl1_Selected(object sender, TabControlEventArgs e)
{
if (tabPagesActiveControl.TryGetValue(e.TabPageIndex, out Control ctrl)) {
BeginInvoke(new Action(() => ActiveControl = ctrl));
}
}
}
As mentioned previously Tab_Open sub is used to create a form as tab.
In Main form (MDI) created Dictionary as
Public tabPagesActiveControl As New Dictionary(Of String, Integer)
In each form when the control is focused the value has been added to dictionary as
Private Sub DateTimePicker1_Leave(sender As Object, e As EventArgs) Handles RadioButton1.GotFocus,
DateTimePicker1.GotFocus, ComboBox1.GotFocus, CheckBox1.GotFocus, Button1.GotFocus, TextBox3.GotFocus, TextBox4.GotFocus, RichTextBox1.GotFocus
If Form1.tabPagesActiveControl.ContainsKey(Form1.TabControl1.SelectedTab.Name) Then
Form1.tabPagesActiveControl(Form1.TabControl1.SelectedTab.Name) = Me.ActiveControl.TabIndex
Else
Form1.tabPagesActiveControl.Add(Form1.TabControl1.SelectedTab.Name, Me.ActiveControl.TabIndex)
End If
End Sub
And when the tab is focused:
Private Sub TabControl1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles TabControl1.SelectedIndexChanged
If tabPagesActiveControl.ContainsKey(Me.TabControl1.SelectedTab.Name) Then
Dim Indxval As String = String.Format(tabPagesActiveControl.Item(Me.TabControl1.SelectedTab.Name))
SendKeys.Send("{TAB " & Indxval & "}")
End If
End Sub
As mentioned in the comments it has flaws. Kindly please check and help or do let me know what can be tried.
Finally I solved the issue after struggling for 8 Days :)
As I mentioned earlier I Open the forms as tabs using the Sub Tab_Open mentioned in the question.
Defined or created a new dictionary in MDI form as
Public tabPagesActiveControl As New Dictionary(Of String, Control)
and defined a control variable as
Dim Sel_Control As Control
Now in each form when the control is focused I have the below code to assign the current control alone to the dictionary:
Private Sub All_Focus(sender As Object, e As EventArgs) Handles TBox_Reg_website.GotFocus,
TBox_Reg_To.GotFocus, TBox_Reg_State.GotFocus, TBox_Reg_PinCD.GotFocus, TBox_Reg_PAN.GotFocus, TBox_Reg_office_num.GotFocus,
TBox_Reg_mobile_num.GotFocus, TBox_Reg_GSTIN.GotFocus, TBox_Reg_fax_no.GotFocus, TBox_Reg_email.GotFocus, TBox_Reg_country.GotFocus,
TBox_Reg_Company.GotFocus, TBox_Reg_City.GotFocus, TBox_Reg_Add2.GotFocus, TBox_Reg_Add1.GotFocus, TB_Curr_website.GotFocus,
TB_Curr_state.GotFocus, TB_Curr_RegTo.GotFocus, TB_Curr_Pincd.GotFocus, TB_Curr_Pan.GotFocus, TB_Curr_office_num.GotFocus,
TB_Curr_Mobile_num.GotFocus, TB_Curr_Gstin.GotFocus, TB_Curr_fax_no.GotFocus, TB_Curr_email.GotFocus, TB_Curr_country.GotFocus,
TB_Curr_Company.GotFocus, TB_Curr_city.GotFocus, TB_Curr_add2.GotFocus, TB_Curr_add1.GotFocus,
PICBox_Reg_Logo.GotFocus, MSP_Reg.GotFocus, Label9.GotFocus, Label8.GotFocus, Label7.GotFocus, Label6.GotFocus, Label5.GotFocus,
Label4.GotFocus, Label3.GotFocus, Label2.GotFocus, Label15.GotFocus, Label14.GotFocus, Label13.GotFocus, Label12.GotFocus,
Label11.GotFocus, Label10.GotFocus, Label1.GotFocus,
ChkBx_Upd_Logo.GotFocus, Chkbox_NoLogo.GotFocus
If Form1.tabPagesActiveControl.ContainsKey(Form1.TabControl1.SelectedTab.Name) Then
Form1.tabPagesActiveControl.Remove(Form1.TabControl1.SelectedTab.Name)
End If
Form1.tabPagesActiveControl.Add(Form1.TabControl1.SelectedTab.Name, Me.ActiveControl)
End Sub
and in the MDI form when tab select index changes having the below code:
Private Sub TabControl1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles TabControl1.SelectedIndexChanged
If tabPagesActiveControl.ContainsKey(Me.TabControl1.SelectedTab.Name) Then
Sel_Control = tabPagesActiveControl.Item(Me.TabControl1.SelectedTab.Name)
Sel_Control.Focus()
End If
End Sub
Thanks :)

How do I get a radio box that permits no selections?

I have a pair of radio buttons on top of a panel to function as a radio box, and it is mostly fine, but I need the user to have the option of leaving both of them unchecked (I wish the user to select zero or one of the options). They are both unchecked when the form is displayed, but after the user checks one of them, it is impossible to revert to the original state. I would expect clicking the selected radio box would clear it (I vaguely remember this from my X/Motif days) but that doesn't seem to happen.
How do I program the radio buttons to allow both of them the be unchecked? Or should I be using some other control for this purpose?
There is no built in way to do what you're asking for. It is not that hard to do it our-self. Here's the sample code which shows how to do that.
C# version:
private void Initialize()
{
radioButton1.AutoCheck = false;
radioButton2.AutoCheck = false;
radioButton1.Click += radioButton_Click;
radioButton2.Click += radioButton_Click;
}
void radioButton_Click(object sender, EventArgs e)
{
RadioButton radio = (RadioButton)sender;
radio.Checked = !radio.Checked;
if (!radio.Checked)
{
return;
}
var otherRadios = radio.Parent
.Controls
.OfType<RadioButton>()
.Where(r => r != radio);
foreach (var r in otherRadios)
{
r.Checked = !radio.Checked;
}
}
Vb.net version:(Converted using http://converter.telerik.com/)
Private Sub Initialize()
radioButton1.AutoCheck = False
radioButton2.AutoCheck = False
AddHandler radioButton1.Click, AddressOf radioButton_Click
AddHandler radioButton2.Click, AddressOf radioButton_Click
End Sub
Private Sub radioButton_Click(sender As Object, e As EventArgs)
Dim radio As RadioButton = DirectCast(sender, RadioButton)
radio.Checked = Not radio.Checked
If Not radio.Checked Then
Return
End If
Dim otherRadios = radio.Parent.Controls.OfType(Of RadioButton)().Where(Function(r) r <> radio)
For Each r As var In otherRadios
r.Checked = Not radio.Checked
Next
End Sub
It should be simple if you think hatke.. Create your custom control
Imports System.ComponentModel
Public Class MyRadio
Inherits RadioButton
Private _permitted As Boolean = True
<DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
<Browsable(True)> _
Public Property Permitted() As Boolean
Get
Return _permitted
End Get
Set(ByVal value As Boolean)
_permitted = value
End Set
End Property
Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
If _permitted Then MyBase.OnClick(e)
End Sub
End Class
HOW TO USE IT?
myRadio1.Permitted = False 'Assigning it to false will not allow you to select it.
You can use checkboxes, they can be checked and unchecked.
If you really want to uncheck a radio button then use the code below:
Private Sub RadioButton1_MouseDown(sender As Object, e As MouseEventArgs) Handles RadioButton1.MouseDown
If RadioButton1.Checked = True Then
Dim thr As New Threading.Thread(AddressOf unticker)
thr.Start()
End If
End Sub
Private Sub unticker()
Threading.Thread.Sleep(100)
Do Until RadioButton1.Checked = False
Invoke(Sub() RadioButton1.Checked = False)
Loop
End Sub
Use this for each radiobutton individually

Multiple Listboxes, One Selection

I have 2 List Boxes on my form, but I only want to be able to make a single selection between both, how would I go about this?
I, of course, tried doing this first...
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
ListBox2.ClearSelected()
End Sub
Private Sub ListBox2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox2.SelectedIndexChanged
ListBox1.ClearSelected()
End Sub
But since that causes the selected index to be changed it clears what you have just selected as well...
Thanks for any help!
You can test the reason why Selected index changed, something like that:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) {
// If listBox2 focused i.e. user clicked list box2 - do nothing:
// one should not try to clear list box2 selection
if (listBox2.Focused)
return;
listBox2.ClearSelected();
}
private void listBox2_SelectedIndexChanged(object sender, EventArgs e) {
// If list box1 is in focus that means that user just have selected itme there;
// so, do nothing: we shouldn't erase user's selection
if (listBox1.Focused)
return;
listBox1.ClearSelected();
}
First, your question is tagged as C# but the code sample is in VB.
Second, I would do it in C# as follows:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
listBox2.SelectedIndexChanged -= new System.EventHandler(this.listBox2_SelectedIndexChanged);
listBox2.ClearSelected();
listBox2.SelectedIndexChanged += new System.EventHandler(this.listBox2_SelectedIndexChanged);
}
And do the same with the other event handler.

Enable/Disable selectAll check box in Infragistics UltraWinGrid

I have used Infragistics UltraWinGrid to display data on the Grid. In this grid, there is one check box column. I have added check box in header in this column to selectAll option.
Now I want to enable/disable this header check box on any button click event to restrict user to perform any action.
Can any one tell me how to do this?
Thanks in advance.
I can think of two options off the top:
1) If you don't want the user to click any of the checkboxes, just hide the entire column if they are not authorized.
2) If you only want to keep the user from selecting all of the items in the grid, add code to the selectAll method to ignore the request if the user is not authorized.
Update
3) If you are using a version of the grid that supports it, you can use:
grid.DisplayLayout.Override.HeaderCheckBoxVisibility = HeaderCheckBoxVisibility.Never
when the form containing the grid is loaded if the user is not authorized.
The check box in the header is provided by a HeaderCheckBoxUIElement and this has an enabled property that can be set to determine if the check box is enabled. To get a reference to the HeaderCheckBoxUIElement you can use the MouseEnterElement and set the Enabled property in that event. For tracking if it is enabled you could use the Tag property of the column.
The code in VB:
Private Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
Dim col As UltraGridColumn = Me.UltraGrid1.DisplayLayout.Bands(0).Columns("OnSite")
col.Tag = (TypeOf col.Tag Is Boolean AndAlso CBool(col.Tag) = False)
End Sub
Private Sub UltraGrid1_MouseEnterElement(sender As Object, e As Infragistics.Win.UIElementEventArgs) Handles UltraGrid1.MouseEnterElement
If TypeOf e.Element Is HeaderCheckBoxUIElement Then
Dim element As HeaderCheckBoxUIElement = DirectCast(e.Element, HeaderCheckBoxUIElement)
element.Enabled = (TypeOf element.Column.Tag Is Boolean AndAlso CBool(element.Column.Tag) = True)
End If
End Sub
The code in C#:
void ultraGrid1_MouseEnterElement(object sender, UIElementEventArgs e)
{
if (e.Element is HeaderCheckBoxUIElement)
{
HeaderCheckBoxUIElement element = (HeaderCheckBoxUIElement)e.Element;
element.Enabled = (element.Column.Tag is bool && (bool)element.Column.Tag == true);
}
}
private void button1_Click(object sender, EventArgs e)
{
UltraGridColumn col = this.ultraGrid1.DisplayLayout.Bands[0].Columns["OnSite"];
col.Tag = (col.Tag is bool && (bool)col.Tag == false);
}