Get panel from button inside and change TableLayoutPanel cell color - vb.net

I have a TableLayoutPanel, panel in each cell, 2 RadioButton in each panel. When I checked the RadioButton, the cell color will change. I know I can do it with assign CheckedChanged event to each RadioButton and hardcode the cell row and column to change the color. I have 15 panels, so will have 30 different CheckedChanged event.
Is there any way that I can use the sender(RadioButton) to get its panel? So that I can use GetCellPosition(panel) to get the cell and use the panel to get which RadioButton in it is checked. Then I can just assign this event to all RadioButtons.

That can be achieved by using the Control.Parent property.
Your code should look something like this:
Private Sub RBs_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton1.CheckedChanged,
RadioButton2.CheckedChanged,
' ...etc.
Dim rb = DirectCast(sender, RadioButton)
Dim pnl = DirectCast(rb.Parent, Panel)
' TODO: Do something with pnl and/or rb.
Console.WriteLine(pnl.Name)
End Sub
Do note, however, that selecting a certain RadioButton will trigger the CheckedChanged event for two RBs; the one that got checked and the one the got unchecked. So, you might want to wrap your code inside If rb.Checked Then ... End If or whatever is appropriate.

Related

How to avoid triggering MouseLeave event when hovering over a child control?

I am trying to make it so if you hover into a panel, it will change its color, and when you hover into a label, the panel will not change its color or go back to default, let me show pictures of what I am trying to explain:
If you didn't hover into anything, it would be at its default state:
If you hovered into it, panel color will change:
Then, if you hover into the label, panel color shouldn't change:
But instead, what it does is if you hover into the label, the panel color goes back to what its default was. This is my code:
Private Sub Panel13_MouseEnter(sender As Object, e As EventArgs) Handles Panel13.MouseEnter
Panel13.BackColor = Color.DarkGreen
End Sub
Private Sub Panel13_MouseLeave(sender As Object, e As EventArgs) Handles Panel13.MouseLeave
Panel13.BackColor = Color.LimeGreen
End Sub
How can I fix this problem? Is there any way to make the code clean or do I have to copy and paste the code and replace words?
You may use the GetChildAtPoint method to check if the mouse cursor is over a child control.
Replace the code in your MouseLeave event handler with the following:
Dim childControl = Panel13.GetChildAtPoint(Panel13.PointToClient(Cursor.Position))
If childControl Is Nothing Then
Panel13.BackColor = Color.LimeGreen
End If

Use a virtual Keyboard on focused Textboxes and DataGridView Cells

In my Form I have various Textboxes that I write into with an in Form keyboard I created using Buttons. I have this code in Form.Load, which uses an event handler to determine which Textbox has the Focus:
For Each control As Control In Me.Controls
If control.GetType.Equals(GetType(TextBox)) Then
Dim textBox As TextBox = control
AddHandler textBox.Enter, Sub() FocussedTextbox = textBox
End If
Next
Then I use this on each button to write a specific character:
Private Sub btnQ_Click(sender As Object, e As EventArgs) Handles btnQ.Click
If btnQ.Text = "Q" Then
FocussedTextbox.Text += "Q"
ElseIf btnQ.Text = "q" Then
FocussedTextbox.Text += "q"
End If
End Sub
Up to that point I'm good and everything works as intended. The problem is I also have a DataGridView I want to write into but can't focus on it selected cells as I do on Textboxes.
I tried this:
For Each control As Control In Me.Controls
If control.GetType.Equals(GetType(TextBox)) Then
Dim textBox As TextBox = control
AddHandler textBox.Enter, Sub() FocussedTextbox = textBox
ElseIf control.GetType.Equals(GetType(DataGridViewCell)) Then
Dim DGVC As DataGridView = control
AddHandler DGVC.CellBeginEdit, Sub() FocussedTextbox = DGVC
End If
Next
But it just selects my last Textbox.
I declared the variable FocussedTextbox as Control so it's not specific to Textbox but any control.
Any help will be greatly appreciated.
To add text to the current ActiveControl using Buttons, these Button must not steal the focus from the ActiveControl (otherwise they become the ActiveControl).
This way, you can also avoid all those FocusedTextbox = textBox etc. and remove that code.
You just need Buttons that don't have the Selectable attribute set. You can use a Custom Control derived from Button and remove ControlStyles.Selectable in its constructor using the SetStyle method:
Public Class ButtonNoSel
Inherits Button
Public Sub New()
SetStyle(ControlStyles.Selectable, False)
End Sub
End Class
Replace your Buttons with this one (or, well, just set the Style if you're already using Custom Controls).
To replace the existing Buttons with this Custom Control:
Add a new class object to your Project, name it ButtonNoSel, copy all the code above inside the new class to replace the two lines of code you find there.
Build the Project. You can find the ButtonNoSel Control in your ToolBox now. Replace your Buttons with this one.
Or, open up the Form's Designer file and replace (CTRL+H) all System.Windows.Forms.Button() related to the Virtual KeyBoard with ButtonNoSel.
Remove the existing event handlers, these are not needed anymore.
Add the same Click event handler in the Constructor of the class that hosts those Buttons (a Form or whatever else you're using).
You can then remove all those event handlers, one for each control, that you have now; only one event handler is needed for all:
Public Sub New()
InitializeComponent()
For Each ctrl As Control In Me.Controls.OfType(Of ButtonNoSel)
AddHandler ctrl.Click, AddressOf KeyBoardButtons_Click
Next
End Sub
Of course, you also don't need to add event handlers to any other control, this is all that's required.
Now, you can filter the Control types you want your keyboard to work on, e.g., TextBoxBase Controls (TextBox and RichTextBox), DataGridView, NumericUpDown etc.
Or filter only special cases that need special treatment (e.g., MonthCalendar).
To add the char corresponding to the Button pressed, you can use SendKeys.Send(): it will insert the new char in the current insertion point, so you don't need any other code to store and reset the caret/cursor position as it happens if you set the Text property of a Control.
In this example, I'm checking whether the ActiveControl is a TextBoxBase Control, then just send the char that the clicked Button holds.
If it's a DataGridView, first send F2 to enter Edit Mode, then send the char.
You could also just send a char (so, no filter would be required), but in this case, you'll replace, not add to, the existing value of that Cell.
Private Sub KeyBoardButtons_Click(sender As Object, e As EventArgs)
Dim selectedButton = DirectCast(sender, Control)
Dim keysToSend = String.Empty
If TypeOf ActiveControl Is TextBoxBase Then
keysToSend = selectedButton.Text
ElseIf TypeOf ActiveControl Is DataGridView Then
Dim ctrl = DirectCast(ActiveControl, DataGridView)
If TypeOf ctrl.CurrentCell IsNot DataGridViewTextBoxCell Then Return
SendKeys.Send("{F2}")
keysToSend = selectedButton.Text
Else
' Whatever else
End If
If Not String.IsNullOrEmpty(keysToSend) Then
SendKeys.Send(keysToSend)
End If
End Sub
► Note that {F2} is sent just once: when the Cell enters Edit Mode, the ActiveControl is a DataGridViewTextBoxEditingControl, hence a TextBox Control, handled by the TextBoxBase filter.
This is how it works (using just the code posted here):

Show ContextMenuStripItem without clicking off the current cell

I'm using an UltraGrid which has a ContextMenuStrip with 2 items. These are shown when right-clicking an UltraGridCell.
However, in order to show them, the user has to first click off the cell to take it out of edit mode, then right click on it to show the ContextMenuStripItems.
This has become confusing and irritating to the user, so I was wondering if there is any way that it can be changed to show them when right clicking whilst still in edit mode?
I've tried this to take it out of edit mode after a key is pressed, but it doesn't work.
Private Sub ugComm_keyup(sender As Object, e As KeyEventArgs) Handles ugComm.KeyUp
ugComm.UpdateData()
If ugComm.ActiveCell.IsInEditMode = True Then
ugComm.ActiveCell.Row.Update()
End If
End Sub
I also tried something in the MouseClick that was suggested on the Infragistics forums, but again it didn't work.
Is there any way that a user right-clicking a cell that is in edit mode can bring up the ContextMenuStripItems rather than this menu?
The above image shows what is currently show when right-clicking a cell in edit mode (The cell is the bottom right white cell). I don't want this to appear, but the CMS instead.
EDIT
I've tried the suggestions in the current answers, but neither of those worked for me. Possibly because the grids are a slightly older version?
My most recent effort was done with the following code:
Private Sub ugComm_MouseDown(sender As Object, e As MouseEventArgs) Handles ugComm.MouseDown
If e.Button = Windows.Forms.MouseButtons.Right Then
Me.cmCommRate.Show(mouseX, mouseY)
End If
End Sub
But this wasn't triggered until the cell was no longer in edit mode.
NEITHER OF THE ANSWERS BELOW RESOLVE THE ISSUE. STILL NEEDS AN ANSWER
When any cell of the grid enters in edit mode a TextBox is drawn over the cell. The nice part here is this text box is reused for all the cells in the grid. When you right click on the cell in edit mode the default context menu, that comes from MS, shows. What you need to do is get this text box and assign it your context menu strip. You can do this by handling ControlAdded event of the grid like this:
' create a field to store the TextBox
Private cellTextBox As TextBox
Private Sub grid_ControlAdded(sender As Object, e As ControlEventArgs) Handles grid.ControlAdded
' Check if added control is TextBox
If TypeOf e.Control Is TextBox Then
' If added control is TextBox store it in your private field and set its ContextMenuStrip
If Me.cellTextBox Is Nothing Then
Me.cellTextBox = DirectCast(e.Control, TextBox)
Me.cellTextBox.ContextMenuStrip = Me.ctx
End If
End If
End Sub
I have tried to write an event handler for the MouseUp event with this code
Private Sub grid_MouseUp(sender As Object, e as MouseEventArgs) Handles grid.KeyUp
grid.PerformAction(UltraGridAction.ExitEditMode)
grid.ContextMenuStrip.Show()
End Sub
and it works.
The ContextMenuStrip was added in code with this text (as example)
ContextMenuStrip ctx = new ContextMenuStrip()
ctx.Items.Add("Test1")
ctx.Items.Add("Test2")
ctx.Items.Add("Test3")
grid.ContextMenuStrip = ctx

How to remove highlight of combobox when an Item is selected in Vb?

In load page event:
I read some data from DB and then add this data to Combo box then select an item as default and enable of combo box changes to false.
When I load this page, the item witch selected highlights with blue color.
How to remove this highlight?
You can modify its SelectionLength property, which gets or sets how many characters have been selected (highlighted).
Just set it to 0 after you have selected the default item and you should be good to go:
ComboBox1.SelectionLength = 0
EDIT:
In your case this code is executed before the Load event has finished. Due to this the form has not been rendered yet, which is why it is not working for you.
The simple fix is to add this in the form's Shown event too:
Private Sub Form1_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
ComboBox1.SelectionLength = 0
End Sub
If you don't want the caret to be in the beginning you can also add this line to set it to the end of the text:
ComboBox1.SelectionStart = ComboBox1.Text.Length
The proposed solution does not work in VB.NET 2016
The easiest way to do is to pass focus to another element like a label in the SelectedIndexChanged event

change the backcolor of a cell in tablelayoutpanel by clicking the button inside it

I have a tableLayoutPanel in a form. There are 10 rows and 10 columns in tableLayoutPanel. Each cell contains a button. So there are 100 buttons. When a user clicks on any of the button I want to change the backcolor of that. Particular cell. How can I achieve this?
TableLayoutPanel's cell does not have a property to control background color. Instead, you can put a panel on it, which would in turn host your button. Assuming your buttons are dynamically created and a generic handler is attached to every one of them, the following code will change back color of the panel when the button it hosts is clicked:
Private Sub Button_Click(sender As System.Object, e As System.EventArgs)
CType(sender, Control).Parent.BackColor = Color.Black
End Sub