I am writing an application in VB.net (using Visual Studio 2022) which has a lot of text boxes. I am wondering if there is a way to write a routine so any time any of the textboxes have the "enter" action called it will highlight the text contained in the textbox, as opposed to writing the code for each individual textbox "enter" routine?
Assuming that "have the "enter" action called" means when it receives focus, the simplest option would be to create your own custom control that includes that functionality, then use that control instead of regular TextBoxes. Creating custom controls is pretty simple when you want to add to an existing control rather than start from srcatch.
Public Class TextBoxEx
Inherits TextBox
Protected Overrides Sub OnEnter(e As EventArgs)
MyBase.OnEnter(e)
SelectAll()
End Sub
End Class
Once you have that class in your project, it's just a matter replacing existing TextBox refrerences in the designer code with that class. If your project targets .NET Framework, you'll have to Show All Files in the Soluion Explorer to access the designer code file. The designer code for a form with a TextBox will look something like this:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.TextBox1 = New System.Windows.Forms.TextBox()
Me.SuspendLayout()
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(12, 12)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(100, 20)
Me.TextBox1.TabIndex = 0
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(800, 450)
Me.Controls.Add(Me.TextBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents TextBox1 As TextBox
End Class
You just need to replace this:
Friend WithEvents TextBox1 As TextBox
with this:
Friend WithEvents TextBox1 As TextBoxEx
and this:
Me.TextBox1 = New System.Windows.Forms.TextBox()
with this:
Me.TextBox1 = New TextBoxEx()
You can even use the Find & Replace functionality in VS to find all the instances you need to replace. Once that's done, everything else is automatic.
Just be sure to have backed up your code before messing with the designer files, in case you break them. Of course, you should be using source control so you should just be able to undo changes to go back to your last good code.
Related
I am currently working on a project using MS VS 2017.
I was able to open the designer and open the forms before. Now, I'm trying to open the same file but all forms' designers cannot be opened. But the project runs smoothly and I can edit the code.
I tried what others have suggested, like cleaning and building the solution, and deleting the obj subfolder, however none of these worked for me. What should I do?
This is what I get every time I try to open the designer:
The designer could not be shown for this file because none of the classes within it can be designed.
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.EnsureDocument(IDesignerSerializationManager manager)
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager manager)
at
Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager serializationManager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.DeferredLoadHandler.Microsoft.VisualStudio.TextManager.Interop.IVsTextBufferDataEvents.OnLoadCompleted(Int32 fReload)
This is the code of the form I am trying to open:
Public Class frmLogin
Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
Application.Exit()
End Sub
Private Sub lblExit_Click_1(sender As Object, e As EventArgs) Handles lblExit.Click
If (MessageBox.Show("Are you sure to Exit?", "Exit from the system", MessageBoxButtons.YesNo, MessageBoxIcon.Information)) = DialogResult.Yes Then
Application.Exit()
End If
End Sub
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
frmDashboard.Show()
Me.Hide()
End Sub
End Class
The file you need to look at is frmLogin.Designer.vb in your project directory. You can see it by right-clicking (in Visual Studio), for instance "btnLogin" in the code that you posted above, then "Go To Implementation". Or just use File Explorer and open the file with NotePad to see inside.
This is where the design for your form is stored. The file contains auto-generated code and data for your form, and seems to be corrupted somehow, maybe it was accidentally edited.
I have no idea what frmLogin actually looks like, but here is a frmLogin.Designer.vb I just created using the names in your code;
I suggest you compare the contents of your file with the example below which should lead to the source of your problem:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class frmLogin
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.btnCancel = New System.Windows.Forms.Button()
Me.btnLogin = New System.Windows.Forms.Button()
Me.lblExit = New System.Windows.Forms.Label()
Me.SuspendLayout()
'
'btnCancel
'
Me.btnCancel.Location = New System.Drawing.Point(310, 130)
Me.btnCancel.Name = "btnCancel"
Me.btnCancel.Size = New System.Drawing.Size(107, 43)
Me.btnCancel.TabIndex = 0
Me.btnCancel.Text = "Cancel"
Me.btnCancel.UseVisualStyleBackColor = True
'
'btnLogin
'
Me.btnLogin.Location = New System.Drawing.Point(310, 192)
Me.btnLogin.Name = "btnLogin"
Me.btnLogin.Size = New System.Drawing.Size(107, 48)
Me.btnLogin.TabIndex = 1
Me.btnLogin.Text = "Log in"
Me.btnLogin.UseVisualStyleBackColor = True
'
'lblExit
'
Me.lblExit.AutoSize = True
Me.lblExit.Location = New System.Drawing.Point(233, 130)
Me.lblExit.Name = "lblExit"
Me.lblExit.Size = New System.Drawing.Size(24, 13)
Me.lblExit.TabIndex = 2
Me.lblExit.Text = "Exit"
'
'frmLogin
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(800, 450)
Me.Controls.Add(Me.lblExit)
Me.Controls.Add(Me.btnLogin)
Me.Controls.Add(Me.btnCancel)
Me.Name = "frmLogin"
Me.Text = "frmLogin"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents btnCancel As Button
Friend WithEvents btnLogin As Button
Friend WithEvents lblExit As Label
End Class
Good luck!
I had the same issue where the project would build and run but the Windows Forms designer refused to display any forms or controls.
I had to delete the ProjectAssemblies directory and reopen the project and then it worked fine.
%LOCALAPPDATA%\Microsoft\VisualStudio*16.0_72ecbfa4*\ProjectAssemblies
Please help! I can not view the Control Parameter Adjustment Form in my VB project, other three forms are normal.
How can I fix this problem?
Here is the Designer.vb code:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Control_Parameter_Adjustment
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.Label1 = New System.Windows.Forms.Label()
Me.GroupBox1 = New System.Windows.Forms.GroupBox()
Me.Label31 = New System.Windows.Forms.Label()
......
End Class
At first, I apologize for my bad english.
This worked for me: If you add an empty form to your project, you can double clik on it, and you can see the following:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
End Class
You can't see that class definition in the other form, probably because this class have dissapeared (I can't explain you why).
Also and probably, you can find the form_Load event in the form code.
Simply rewrite this class, changing the Form Name in class definition. Then, you can see the designer. The icon also change.
Can I maintain vb.net windows form designer code in .vb?
i.e I wanted to ask whether I can maintain only one .vb file for both form design and logic part, instead of having one designer.vb for form design part and .vb file for logic part?
Here is a functional sample:
_
Partial Class Form1
Inherits System.Windows.Forms.Form
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
Public Sub Intiialize()
'Form overrides dispose to clean up the component list.
InitializeComponent()
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
End Sub
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.Text = "Form1"
End Sub
End Class
I'm reasonably new to programming and soon I will be creating a program and would like to change the colour of a selected row via a button click.
I have been attempting this but I don't even know where to begin. If someone could point me in the correct direction it would be much appreciated.
Thanks ^.^
You could simply create a new control, then change the designer to inherit from the listbox control.
the designer code would then look something like this (vs2010):
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class UserControl1
Inherits ListBox
'UserControl overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
End Sub
End Class
To see the designer code, select "Show All Files" (button at the top of your solution explorer). Then expand the new control node in your solution explorer.
then change the line:
Inherits System.Windows.Forms.UserControl
to:
Inherits ListBox
and finally delete delete the line:
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Hope that helps.
I have a Windows form with two combo boxes. The SelectedValue property of each combo box is data bound to a property on a simple DTO. The options for each combo box are drawn from a list of model objects. I only require the controls on the form to update the DTO; I have no need to modify any of the DTO's properties programmatically and see the corresponding control being updated - i.e., I only need one-way (control -> source) data binding to work.
When the user changes the value of the first combo box, the options for the second combo box will change completely. However, I have run into two issues with this setup that I cannot figure out why they occur or how to solve them:
Whenever the first combo box is changed, an NRE is generated and swallowed by the data binding framework (I can see it thrown in the Immediate Window of the Visual Studio IDE), which tips me off that something isn't set up correctly. Changing the second combo box or any other unrelated, data bound control (combo box or otherwise) does not generate an NRE.
Also whenever the first combo box is changed, after generating the NRE mentioned above, the second combo box loads successfully, but the first combo box's selected index resets to -1. I suspect this is because the data binding's "push" event fires to update the controls, and for some reason, the value of my DTO's property backing the first combo box gets reset to NULL / Nothing.
Does anyone have any idea why these things occur? I mocked up my problem, which exhibits the two issues above. I also added a third combo box that has nothing to do with either of the first two, just as a sanity check to show that a combo box without any dependency on another combo box works fine.
This code replicates the issues - paste as the code for the default Form1 class of a Visual Basic Windows Forms project (3.5 Framework).
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Windows.Forms
Public Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.cboA = New System.Windows.Forms.ComboBox()
Me.cboB = New System.Windows.Forms.ComboBox()
Me.cboC = New System.Windows.Forms.ComboBox()
Me.SuspendLayout()
'
'cboA
'
Me.cboA.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
Me.cboA.FormattingEnabled = True
Me.cboA.Location = New System.Drawing.Point(120, 25)
Me.cboA.Name = "cboA"
Me.cboA.Size = New System.Drawing.Size(121, 21)
Me.cboA.TabIndex = 0
'
'cboB
'
Me.cboB.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
Me.cboB.FormattingEnabled = True
Me.cboB.Location = New System.Drawing.Point(120, 77)
Me.cboB.Name = "cboB"
Me.cboB.Size = New System.Drawing.Size(121, 21)
Me.cboB.TabIndex = 1
'
'cboC
'
Me.cboC.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
Me.cboC.FormattingEnabled = True
Me.cboC.Location = New System.Drawing.Point(120, 132)
Me.cboC.Name = "cboC"
Me.cboC.Size = New System.Drawing.Size(121, 21)
Me.cboC.TabIndex = 2
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(284, 262)
Me.Controls.Add(Me.cboC)
Me.Controls.Add(Me.cboB)
Me.Controls.Add(Me.cboA)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
Friend WithEvents cboA As System.Windows.Forms.ComboBox
Friend WithEvents cboB As System.Windows.Forms.ComboBox
Friend WithEvents cboC As System.Windows.Forms.ComboBox
Private _DataObject As MyDataObject
Private _IsInitialized As Boolean = False
Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
_DataObject = New MyDataObject()
BindControls()
End Sub
Private Sub BindControls()
LoadComboA(cboA)
Dim cmbABinding As New Binding("SelectedValue", _DataObject, "ValueA", True, DataSourceUpdateMode.OnPropertyChanged)
cboA.DataBindings.Add(cmbABinding)
Dim cmbBBinding As New Binding("SelectedValue", _DataObject, "ValueB", True, DataSourceUpdateMode.OnPropertyChanged)
cboB.DataBindings.Add(cmbBBinding)
LoadComboC(cboC)
Dim cmbCBinding As New Binding("SelectedValue", _DataObject, "ValueC", True, DataSourceUpdateMode.OnPropertyChanged)
cboC.DataBindings.Add(cmbCBinding)
End Sub
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
MyBase.OnLoad(e)
_IsInitialized = True
cboA.SelectedIndex = 0
cboC.SelectedIndex = 0
End Sub
Private Sub ComboA_SelectedValueChanged(ByVal sender As Object, ByVal e As EventArgs) Handles cboA.SelectedValueChanged
If _IsInitialized Then
LoadComboB(cboB, cboA.SelectedValue.ToString())
cboB.SelectedIndex = 0
End If
End Sub
Private Sub LoadComboA(ByVal cmbBox As ComboBox)
Dim someData As New Dictionary(Of String, String)()
someData.Add("Value1", "Text 1")
someData.Add("Value2", "Text 2")
someData.Add("Value3", "Text 3")
cmbBox.DataSource = someData.ToList()
cmbBox.DisplayMember = "Value"
cmbBox.ValueMember = "Key"
End Sub
Private Sub LoadComboB(ByVal cmbBox As ComboBox, ByVal selector As String)
Dim someSubData As New Dictionary(Of String, String)()
Select Case selector
Case "Value1"
someSubData.Add("SubValue1", "Value1 - Sub Text 1")
someSubData.Add("SubValue2", "Value1 - Sub Text 2")
someSubData.Add("SubValue3", "Value1 - Sub Text 3")
Case "Value2"
someSubData.Add("SubValue4", "Value2 - Sub Text 4")
someSubData.Add("SubValue5", "Value2 - Sub Text 5")
someSubData.Add("SubValue6", "Value2 - Sub Text 6")
Case "Value3"
someSubData.Add("SubValue7", "Value3 - Sub Text 7")
someSubData.Add("SubValue8", "Value3 - Sub Text 8")
someSubData.Add("SubValue9", "Value3 - Sub Text 9")
End Select
cmbBox.DataSource = someSubData.ToList()
cmbBox.DisplayMember = "Value"
cmbBox.ValueMember = "Key"
End Sub
Private Sub LoadComboC(ByVal cmbBox As ComboBox)
Dim someData As New Dictionary(Of String, String)()
someData.Add("Value100", "Text 100")
someData.Add("Value101", "Text 101")
cmbBox.DataSource = someData.ToList()
cmbBox.DisplayMember = "Value"
cmbBox.ValueMember = "Key"
End Sub
End Class
Public Class MyDataObject ' DTO class
Private _ValueA As String
Public Property ValueA() As String
Get
Return _ValueA
End Get
Set(ByVal value As String)
_ValueA = value
End Set
End Property
Private _ValueB As String
Public Property ValueB() As String
Get
Return _ValueB
End Get
Set(ByVal value As String)
_ValueB = value
End Set
End Property
Private _ValueC As String
Public Property ValueC() As String
Get
Return _ValueC
End Get
Set(ByVal value As String)
_ValueC = value
End Set
End Property
End Class
DataBinding can be difficult to debug when it misbehaves. There are two things going wrong here, enough to make it hard to diagnose. The first thing you didn't count on is that the SelectedValueChanged event fires before the currency manager updates the bound object. That normally isn't a problem but your event handler has a side-effect. The next thing you didn't count on is that changing one property of the bound object causes the binding of all other properties to be updated as well.
And there's the rub, _DataObject.ValueA is still Nothing when you update combo B. Which updates _DataObject.ValueB. So the currency manager updates combo A again, trying to make it match the value of Nothing in property ValueA. Which is what also produced the NullReferenceException.
One possible fix is to delay the side-effect in your SelectedValueChanged event handler and postpone it until the currency manager updated the bound object. Than can be cleanly done by using Control.BeginInvoke(), the target runs when the UI thread goes idle again. This fixed your problem:
Private Sub ComboA_SelectedValueChanged(ByVal sender As Object, ByVal e As EventArgs) Handles cboA.SelectedValueChanged
If _IsInitialized Then Me.BeginInvoke(New MethodInvoker(AddressOf LoadB))
End Sub
Private Sub LoadB()
LoadComboB(cboB, cboA.SelectedValue.ToString())
cboB.SelectedIndex = 0
End Sub
There's probably a cleaner fix, updating _DataObject instead of trying to update the combobox. But you made that a bit difficult by using a Dictionary, I didn't pursue it.