I have written a small piece of code to change the display member of my combo box when a radio button is selected. The only problem I'm having is that when I switch between the radio buttons the combo box disappears then comes back a second later, is there any way of resolving this problem.
Private Sub SearchOptionChange(sender As Object, e As EventArgs) Handles RBExchange.CheckedChanged, RBPostcode.CheckedChanged
Dim RB As RadioButton = CType(sender, RadioButton)
If RB.Name = "RBExchange" AndAlso RB.Checked Then
ComboBox1.DisplayMember = "Exchange"
ComboBox1.Text = ""
ElseIf RB.Name = "RBPostcode" AndAlso RB.Checked Then
ComboBox1.DisplayMember = "Postcode"
ComboBox1.Text = ""
End If
End Sub
I used the following to reproduce your issue and it only happens when DropDownStyle is set to Simple. So if possible set DropDownStyle to DropDown.
Note I used 5,000 items and no blinking, jumped to 10,000 and the blinking was there so in addition to the suggestion above consider if possible to reduce how many items in the ComboBox if business logic allows.
Test used and note that even SuspendLayout and ResumeLayout did not help when DropDownStyle is set to Simple.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) _
Handles MyBase.Load
Dim ItemList As New List(Of item)
For x As Integer = 0 To 50000
ItemList.Add(New item With
{
.Exchange = "E" & x.ToString,
.PostCode = "P" & x.ToString
})
Next
ComboBox1.DisplayMember = "Exchange"
ComboBox1.DataSource = ItemList
End Sub
Private Sub RBExchange_CheckedChanged(sender As Object, e As EventArgs) _
Handles RBExchange.CheckedChanged, RBPostcode.CheckedChanged
Dim RB As RadioButton = CType(sender, RadioButton)
RB.SuspendLayout()
If RB.Name = "RBExchange" AndAlso RB.Checked Then
ComboBox1.DisplayMember = "Exchange"
ComboBox1.Text = ""
ElseIf RB.Name = "RBPostcode" AndAlso RB.Checked Then
ComboBox1.DisplayMember = "Postcode"
ComboBox1.Text = ""
End If
RB.ResumeLayout()
End Sub
End Class
Public Class item
Public Property Exchange
Public Property PostCode
End Class
Related
The code shown below should allow any button on the page to change colour except for the ones named in the first if statement. This code was working but now does nothing when the button is clicked. The button should turn yellow but just stays the default colour. Also is there anyway I can manipulate the code so only one button can be red at a time instead of allowing multiple red buttons. When reading into this. I cannot find any help for vb. Can anyone help?
Personally, I think it may be to do with thePublic Sub since the message box does not appear when a field is empty.
Public Sub btn_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Click
Try
Dim btn As Button = sender
If btn.Name = "BtnUpdate" Or btn.Name = "BtnBackCust" Or btn.Name = "BtnConfirm" Then
ElseIf TxtFirstName.Text = "" Or TxtLastName.Text = "" Or TxtAddress.Text = "" Or cboCountry.SelectedItem = "" Or cboRoomType.SelectedItem = "" Then
MsgBox("You must populate all fields")
Else
btn.BackColor = Color.Red
btn.Text = ChosenRoom
End If
Catch ex As Exception
End Try
End Sub
Instead of using the MyBase.Click Event, create an Handle for each Button on your Form Load:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each Button As Button In Me.Controls.OfType(Of Button)()
If Button.Name <> "BtnUpdate" AndAlso Button.Name <> "BtnBackCust" AndAlso Button.Name <> "BtnConfirm" Then
AddHandler Button.Click, AddressOf ChangeColor
End If
Next
End Sub
The ChangeColor sub, also create the RedButton variable to keep track of what is the currently red button:
Private RedButton As Button = Nothing
Private Sub ChangeColor(Sender As Object, e As EventArgs)
If TypeOf Sender Is Button Then
If TxtFirstName.Text = "" OrElse TxtLastName.Text = "" OrElse TxtAddress.Text = "" OrElse cboCountry.SelectedItem = "" OrElse cboRoomType.SelectedItem = "" Then
MsgBox("You must populate all fields")
Else
Dim SenderButton As Button = Sender
If RedButton IsNot Nothing Then
RedButton.BackColor = Me.BackColor
End If
If SenderButton IsNot RedButton Then 'This if will toogle the button between Red and the Normal color
SenderButton.BackColor = Color.Red
End If
RedButton = Sender
End If
End If
End Sub
I tried to provide auto-complete text in datagridview. But, I got auto-complete text in all column and after clicking on third column (with combobox) application start displaying error on editing other cells.
I want auto-complete text box in first column i.e. "Name" only. I cannot manage code so that auto-complete doesn't show in second column i.e. "Age" and also error not occurred after clicking on combobox column.
The code is As follow.
Public Class Form1
Private Sub appData(ByVal data As AutoCompleteStringCollection, ByVal c As String)
data.Add("Ravi")
data.Add("Raj")
data.Add("Raja")
data.Add("r " & c)
End Sub
Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
Try
MsgBox(e.Control.ToString)
Dim header As String = DataGridView1.Columns(0).HeaderText
If TypeOf e.Control Is TextBox AndAlso header.Equals("Name") AndAlso DataGridView1.CurrentCell.ColumnIndex = 0 Then
If DataGridView1.CurrentCell.ColumnIndex = 0 Then
Dim text As TextBox = TryCast(e.Control, TextBox)
If text IsNot Nothing Then
text.AutoCompleteMode = AutoCompleteMode.Suggest
text.AutoCompleteSource = AutoCompleteSource.CustomSource
Dim data As AutoCompleteStringCollection = New AutoCompleteStringCollection()
appData(data, DataGridView1.CurrentCellAddress.ToString)
text.AutoCompleteCustomSource = data
End If
Else
Dim text As TextBox = TryCast(e.Control, TextBox)
text.AutoCompleteCustomSource = Nothing
text.AutoCompleteSource = AutoCompleteSource.None
text.AutoCompleteMode = AutoCompleteMode.None
End If
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DataGridView1.Columns.Add("ColName", "Name")
DataGridView1.Columns.Add("ColAge", "Age")
Dim ComCol As New DataGridViewComboBoxColumn
ComCol.Items.Add(1)
ComCol.Items.Add(2)
ComCol.HeaderText = "Combobox Col"
DataGridView1.Columns.Add(ComCol)
End Sub
End Class
Do a test in Else clause as :
If header.Equals("Name") Then
If DataGridView1.CurrentCell.ColumnIndex = 0 Then
Dim text As TextBox = TryCast(e.Control, TextBox)
If text IsNot Nothing Then
text.AutoCompleteMode = AutoCompleteMode.Suggest
text.AutoCompleteSource = AutoCompleteSource.CustomSource
Dim data As AutoCompleteStringCollection = New AutoCompleteStringCollection()
appData(data, DataGridView1.CurrentCellAddress.ToString)
text.AutoCompleteCustomSource = data
End If
ElseIf TypeOf e.Control Is TextBox Then
Dim text As TextBox = TryCast(e.Control, TextBox)
text.AutoCompleteCustomSource = Nothing
text.AutoCompleteSource = AutoCompleteSource.None
text.AutoCompleteMode = AutoCompleteMode.None
End If
End If
Private Sub DataGridView1_DataError(sender As Object, e As DataGridViewDataErrorEventArgs) Handles DataGridView1.DataError
Try
Catch ex As Exception
End Try
End Sub
Use just :
If header.Equals("Name") Then
instead of :
If TypeOf e.Control Is TextBox AndAlso header.Equals("Name") AndAlso
DataGridView1.CurrentCell.ColumnIndex = 0 Then
I believe the problem is that your DataGridView1_EditingControlShowing is firing more often than you realize.
Perhaps you should just do your autocomplete work on form load event instead? That way, it only has to run once...
The 'autocomplete work' I'm talking about, being this part:
text.AutoCompleteMode = AutoCompleteMode.Suggest
text.AutoCompleteSource = AutoCompleteSource.CustomSource
Dim data As AutoCompleteStringCollection = New AutoCompleteStringCollection()
appData(data, DataGridView1.CurrentCellAddress.ToString)
text.AutoCompleteCustomSource = data
HI their i am trying to create a dynamic text editor which will have tabs and option to add, remove datagridviews using buttons. Also in datagridviews, columns and rows could be added programmatically. I have reached till following code:
Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
Dim tbpg As TabPage = TabControl1.SelectedTab
Dim dgview As New DataGridView
Controls.Add(dgview)
dgview.Location = New Point(5, 5)
dgview.Size = New Size(250, 250)
dgview.ColumnCount = 5
dgview.RowCount = 5
tbpg.Controls.Add(dgview)
End Sub
also
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
If RadioButton1.Checked = True Then
Dim clm As New DataGridViewTextBoxColumn
clm.DataPropertyName = "Property Name"
clm.HeaderText = "Header Name"
clm.Name = "Column Name"
DataGridView1.Columns.Add(clm)
ElseIf RadioButton2.Checked = True Then
DataGridView1.Rows.Add()
End If
End Sub
The problem is initially there is no datagridview, so the line DataGridView1.Columns.Add(clm) gives error. So i think there should be a currentdatagridview or selecteddatagridview property.
Any help appreciated.
You can change the scope of the initial declaration and make it private to your form.
Private dgview As DataGridView
Then when you create it, refer to the local private
dgview = New DataGridView
Lastly in your column creation, just keep referring to dgview
dgview.Columns.Add()
That should cover your requirement.
Full code sample:
Public Class Form1
Private dgView As DataGridView
Private Sub createDGV()
dgView = New DataGridView
TabControl1.SelectedTab.Controls.Add(dgView)
dgView.Location = New Point(5, 5)
dgView.Size = New Size(250, 250)
dgView.ColumnCount = 5
dgView.RowCount = 5
End Sub
Private Sub addColumn()
Dim thisDGV As DataGridView = findMyDGV()
If RadioButton1.Checked = True Then
Dim clm As DataGridViewTextBoxColumn = New DataGridViewTextBoxColumn
clm.DataPropertyName = "Property Name"
clm.HeaderText = "Header Name"
clm.Name = "Column Name"
thisDGV.Columns.Add(clm)
ElseIf RadioButton2.Checked = True Then
thisdgv.Rows.Add()
End If
End Sub
Private Function findMyDGV() As DataGridView
For Each ctrl As Control In TabControl1.SelectedTab.Controls
If TypeOf ctrl Is DataGridView Then
Return ctrl
End If
Next
End Function
Private Sub TestDGVButton_Click(sender As System.Object, e As System.EventArgs) Handles TestButton.Click
Try
createDGV()
addColumn()
Catch ex As Exception
MessageBox.Show(String.Concat("An error occurred: ", ex.Message))
End Try
End Sub
End Class
I have a list box bound to a list is a class. All works fine until I try to add a new item to the list. during this process the data source is set to nothing to refresh the list and apparently 'Refresh' doesn't do it. The list gets refreshed and the other controls bound to the listboxes data show that the list is there and is correct however the list appears empty although it does show scroll bars. I have tried to change the font color, just in case.. Nothing!
Does someone know why this happens? how to fix it? Or a better way to refresh?
Code:
Private Sub btnNew_Click(sender As Object, e As EventArgs) Handles btnNew.Click
'lbNames is the listbox carrying all the data
Dim oContacts As List(Of clsContact) = lbNames.DataSource
lbNames.DataSource = Nothing
'Build the new Item, add it to the collection
Dim oNewCont As New clsContact
oNewCont.Editable = True
oNewCont.IsActive = True
oNewCont.Firstname = "Jimmy"
oNewCont.Lastname = "Smith"
oContacts.Add(oNewCont)
lbNames.Refresh()
' Re-Set up Autocomplete text box
Dim MySource As New AutoCompleteStringCollection()
For Each oc As clsContact In oContacts
MySource.Add(oc.FullName)
Next
txtName.AutoCompleteMode = AutoCompleteMode.Suggest
txtName.AutoCompleteCustomSource = MySource
txtName.AutoCompleteSource = AutoCompleteSource.CustomSource
'Set List Box data back to the collection
lbNames.DataSource = oContacts
lbNames.DisplayMember = "FullName"
End Sub
The starting LOAD:
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim oCont As List(Of clsContact)
lbNames.DrawMode = DrawMode.OwnerDrawVariable
Dim oTypes As List(Of clsPhoneType) = loadTypes()
cboPhoneType.DataSource = oTypes
cboPhoneType.DisplayMember = "Type"
cboPhoneType.ValueMember = "ID"
oCont = LoadNames()
lbNames.DataSource = oCont
lbNames.DisplayMember = "FullName"
Dim MySource As New AutoCompleteStringCollection()
For Each oc As clsContact In oCont
MySource.Add(oc.FullName)
Next
txtName.AutoCompleteMode = AutoCompleteMode.Suggest
txtName.AutoCompleteCustomSource = MySource
txtName.AutoCompleteSource = AutoCompleteSource.CustomSource
End Sub
Private Sub lbNames_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles lbNames.DrawItem
e.DrawBackground()
Dim textBrush As Brush = Brushes.Black
Dim drawFont As System.Drawing.Font = e.Font
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
e.Graphics.FillRectangle(Brushes.WhiteSmoke, e.Bounds)
End If
Dim oCont As clsContact = DirectCast(sender, System.Windows.Forms.ListBox).Items(e.Index)
If oCont.IsActive Then
textBrush = Brushes.Black
If oCont.IsDirty Then textBrush = Brushes.LightCoral
Else
textBrush = Brushes.LightGray
End If
Dim str = oCont.FullName
e.Graphics.DrawString(str, e.Font, textBrush, e.Bounds, StringFormat.GenericDefault)
e.DrawFocusRectangle()
End Sub
You're using the wrong tools. The List(Of T) doesn't raise any events whatsoever. When bound to a control, the control doesn't know if any items are added/removed/moved. Luckily, the BindingList(Of T) comes to rescue. It will raise a ListChanged event whenever the list is modified. As a bonus, if your class/model implements the INotifyPropertyChanged interface, the control will also reflect property changes.
lbNames.DataSource = New BindingList(Of clsContact)(oCont)
Here's a sample form to show you the basics:
Imports System.ComponentModel
Public Class Form1
Public Sub New()
Me.InitializeComponent()
Me.btnAdd = New Button With {.TabIndex = 0, .Dock = DockStyle.Top, .Height = 30, .Text = "Add new contact"}
Me.btnChange = New Button With {.TabIndex = 1, .Dock = DockStyle.Top, .Height = 30, .Text = "Change random contact name"}
Me.lbContacts = New ListBox With {.TabIndex = 2, .Dock = DockStyle.Fill}
Me.Controls.AddRange({Me.lbContacts, Me.btnChange, Me.btnAdd})
End Sub
Private Sub HandleMeLoad(sender As Object, e As EventArgs) Handles Me.Load
Dim list As New List(Of Contact)
For i As Integer = 1 To 10
list.Add(New Contact With {.Name = String.Format("Contact # {0}", i)})
Next
Me.lbContacts.DataSource = New BindingList(Of Contact)(list)
Me.lbContacts.DisplayMember = "Name"
End Sub
Private Sub HandleButtonAddClick(sender As Object, e As EventArgs) Handles btnAdd.Click
Dim list As BindingList(Of Contact) = DirectCast(Me.lbContacts.DataSource, BindingList(Of Contact))
list.Add(New Contact With {.Name = String.Format("Contact # {0}", (list.Count + 1))})
End Sub
Private Sub HandleButtonChangeClick(sender As Object, e As EventArgs) Handles btnChange.Click
Static rnd As New Random()
Dim list As BindingList(Of Contact) = DirectCast(Me.lbContacts.DataSource, BindingList(Of Contact))
If (list.Count > 0) Then
With list.Item(rnd.Next(0, list.Count))
.Name = Guid.NewGuid().ToString()
End With
End If
End Sub
Public Class Contact
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Public Property Name As String
Get
Return Me.m_name
End Get
Set(value As String)
If (value <> Me.m_name) Then
Me.m_name = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Name"))
End If
End Set
End Property
Private m_name As String
End Class
Private WithEvents btnAdd As Button
Private WithEvents btnChange As Button
Private WithEvents lbContacts As ListBox
End Class
It seems that the solution to fixing this problem is to flip the drawmode back to normal.
adding:
lbNames.DrawMode = DrawMode.Normal
lbNames.DrawMode = DrawMode.OwnerDrawVariable
Fixes the problem.
I guess what is happening is that the drawing handler is becoming disconnected for some reason so the contests of the list are not redrawn when the data source is attached.
My new working code:
Private Sub btnNew_Click(sender As Object, e As EventArgs) Handles btnNew.Click
'lbNames is the listbox carrying all the data
Dim oContacts As List(Of clsContact) = lbNames.DataSource
lbNames.DataSource = Nothing
'Build the new Item, add it to the collection
Dim oNewCont As New clsContact
oNewCont.Editable = True
oNewCont.IsActive = True
oNewCont.Firstname = "Jimmy"
oNewCont.Lastname = "Smith"
oContacts.Add(oNewCont)
' Re-Set up Autocomplete text box
Dim MySource As New AutoCompleteStringCollection()
For Each oc As clsContact In oContacts
MySource.Add(oc.FullName)
Next
txtName.AutoCompleteMode = AutoCompleteMode.Suggest
txtName.AutoCompleteCustomSource = MySource
txtName.AutoCompleteSource = AutoCompleteSource.CustomSource
'Set List Box data back to the collection
lbNames.DataSource = oContacts
lbNames.DisplayMember = "FullName"
lbNames.DrawMode = DrawMode.Normal
lbNames.DrawMode = DrawMode.OwnerDrawVariable
End Sub
So interesting dilemma, I've managed to make a label completely invisible, to where I can use it for a click event on certain parts of a picture.
I then use that click event to call another picturebox into focus using picturebox3.visible = true..
The issue I'm having is when it's calling that picturebox visibility..the controls from the new picturebox (Invisible labels) seem to not function or be missing from the picture in picturebox2 completely.
I need to do this with about 30 different pictures in order to create a kind of "emulator" project for someone.
Any ideas on this? I can post code if needed. Picturebox + controls on picturebox = headache.
Public Class InvisibleLabel
Inherits Label
Public Sub New()
Me.SetStyle(ControlStyles.Opaque, True)
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, False)
End Sub
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim CC As CreateParams = MyBase.CreateParams
CC.ExStyle = CC.ExStyle Or &H20
Return CC
End Get
End Property
End Class
This is the code for the invisible label, then I'm just using picturebox2.visible = true when certain parts of a picture are clicked.
I made 3 textboxes
textbox1 for X 'just for you to see
textbox2 for Y 'just for you to see
and
CurPicture to compare current image
my picturebox is 300,300
Private Sub PictureBox1_MouseClick(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseClick
Dim LocX As Integer = e.X
Dim LocY As Integer = e.Y
TextBox1.Text = e.X.ToString
TextBox2.Text = e.Y.ToString
If LocX > 200 Then ' click right side op the picture , change LocX With LocY to make it bottom
If CurPicture.Text = "1" Then
PictureBox1.Image = My.Resources.Pic2
CurPicture.Text = "2"
ElseIf CurPicture.Text = "2" Then
PictureBox1.Image = My.Resources.Pic3
CurPicture.Text = "3"
ElseIf CurPicture.Text = "3" Then
PictureBox1.Image = My.Resources.Pic4
CurPicture.Text = "4"
ElseIf CurPicture.Text = "4" Then
PictureBox1.Image = My.Resources.Pic5
CurPicture.Text = "5"
ElseIf CurPicture.Text = "5" Then
PictureBox1.Image = My.Resources.Pic1
CurPicture.Text = "1"
End If
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PictureBox1.Image = My.Resources.Pic1
CurPicture.Text = "1"
End Sub
Hope this will help you get on the way :)
Use:
Private Sub PictureBox_MouseDown(sender As Object, e As MouseEventArgs) _
Handles PictureBox.MouseDown
'The code to change the picture goes here
End Sub