WinForms Object Databinding Performance Issue - vb.net

I have created a simple VB .NET Application. 1 Form with 2 TextBoxes bounded to a class with 2 properties, Property1 and Property2. If I input text in TextBox1, binding process causes reading of second property, Property2. Why? I don't want that if I change a property, all bounded controls updates their data.
Code:
' Class1.vb
Imports System.ComponentModel
Public Class Class1
Private property1Value As String
Public Property Property1() As String
Get
Return property1Value
End Get
Set(ByVal value As String)
property1Value = value
End Set
End Property
Private property2Value As String
Public Property Property2() As String
Get
Return property2Value
End Get
Set(ByVal value As String)
property2Value = value
End Set
End Property
End Class
' Form1.Designer.vb
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Form esegue l'override del metodo Dispose per pulire l'elenco dei componenti.
<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
'Richiesto da Progettazione Windows Form
Private components As System.ComponentModel.IContainer
'NOTA: la procedura che segue è richiesta da Progettazione Windows Form
'Può essere modificata in Progettazione Windows Form.
'Non modificarla nell'editor del codice.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Me.TextBox1 = New System.Windows.Forms.TextBox()
Me.TextBox2 = New System.Windows.Forms.TextBox()
Me.Class1BindingSource = New System.Windows.Forms.BindingSource(Me.components)
CType(Me.Class1BindingSource, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'TextBox1
'
Me.TextBox1.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.Class1BindingSource, "Property1", True, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged))
Me.TextBox1.Location = New System.Drawing.Point(12, 12)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(100, 22)
Me.TextBox1.TabIndex = 2
'
'TextBox2
'
Me.TextBox2.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.Class1BindingSource, "Property2", True, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged))
Me.TextBox2.Location = New System.Drawing.Point(12, 40)
Me.TextBox2.Name = "TextBox2"
Me.TextBox2.Size = New System.Drawing.Size(100, 22)
Me.TextBox2.TabIndex = 3
'
'Class1BindingSource
'
Me.Class1BindingSource.DataSource = GetType(WindowsApplication1.Class1)
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(8.0!, 16.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(282, 255)
Me.Controls.Add(Me.TextBox2)
Me.Controls.Add(Me.TextBox1)
Me.Name = "Form1"
Me.Text = "Form1"
CType(Me.Class1BindingSource, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents Class1BindingSource As System.Windows.Forms.BindingSource
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
Friend WithEvents TextBox2 As System.Windows.Forms.TextBox
End Class
' Form1.vb
Imports System.ComponentModel
Public Class Form1
Private Class1 As New Class1
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Class1.Property1 = "Prop1"
Class1.Property2 = "Prop2"
Class1BindingSource.DataSource = Class1
End Sub
End Class

Related

Form childs doesn't resize when form resize because of minimumsize

I have a form with a SplitContainer in dock fill. In panel 1 of the split container I have buttons, in panel 2, I have a UserControl in dock fill. The Usercontrol classes in panel2 change depending on buttons clicked in panel1 but is kept dock fill.
Each Usercontrol have a minimum size.
The MinimumSize of the form is recalculate every time I change UCs and also when I move the splitter. This looks perfectly fine.
When I resize the form manually, everything follow as intended by default : fine. Meaning, the form can't be resized under minimum size value.
When I move the splitter manually, everything follow as intended by default : fine. Meaning, panel 1 and panel 2 UC resize as well as all the children.
But, when at any given moment if the form is at minimum size and I try to move the slider. The form resize properly to allow panel 2 UC minimum size to fit BUT the UC doesn't resize...
Any idea why and how to fix it?
As suggested, I simplified the application to a minimum and here is the code of the MainForm :
Public Class MainForm
Private Sub SetMinSize()
Dim borderWidth = Me.Width - Me.ClientSize.Width
Me.MinimumSize = New Size(borderWidth + Me.SplitContainerMain.Panel1.Size.Width + Me.SplitContainerMain.SplitterWidth + Me.MainUserControl.MinimumSize.Width,
Me.MinimumSize.Height)
End Sub
Private Sub MainUserControl_ControlAdded(sender As Object, e As ControlEventArgs)
Me.SetMinSize()
End Sub
Private Sub SplitContainerMain_SplitterMoved(sender As Object, e As SplitterEventArgs) Handles SplitContainerMain.SplitterMoved
Me.SetMinSize()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.SuspendLayout()
Me.SplitContainerMain.Panel2.Controls.Remove(Me.MainUserControl)
Try ' The try catch avoid error in case the handle is not created
RemoveHandler Me.MainUserControl.ControlAdded, AddressOf Me.MainUserControl_ControlAdded
Catch ex As Exception
End Try
Me.MainUserControl.Dispose()
Me.MainUserControl = New UC1UserControl
Me.MainUserControl.Dock = DockStyle.Fill
Me.SplitContainerMain.Panel2.Controls.Add(Me.MainUserControl)
AddHandler Me.MainUserControl.ControlAdded, AddressOf Me.MainUserControl_ControlAdded
Me.ResumeLayout()
Me.SetMinSize()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Me.SuspendLayout()
Me.SplitContainerMain.Panel2.Controls.Remove(Me.MainUserControl)
Try ' The try catch avoid error in case the handle is not created
RemoveHandler Me.MainUserControl.ControlAdded, AddressOf Me.MainUserControl_ControlAdded
Catch ex As Exception
End Try
Me.MainUserControl.Dispose()
Me.MainUserControl = New UC2UserControl
Me.MainUserControl.Dock = DockStyle.Fill
Me.SplitContainerMain.Panel2.Controls.Add(Me.MainUserControl)
AddHandler Me.MainUserControl.ControlAdded, AddressOf Me.MainUserControl_ControlAdded
Me.ResumeLayout()
Me.SetMinSize()
End Sub
End Class
And this is the designer:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class MainForm
Inherits System.Windows.Forms.Form
'Form remplace la méthode Dispose pour nettoyer la liste des composants.
<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
'Requise par le Concepteur Windows Form
Private components As System.ComponentModel.IContainer
'REMARQUE : la procédure suivante est requise par le Concepteur Windows Form
'Elle peut être modifiée à l'aide du Concepteur Windows Form.
'Ne la modifiez pas à l'aide de l'éditeur de code.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.SplitContainerMain = New System.Windows.Forms.SplitContainer()
Me.Button2 = New System.Windows.Forms.Button()
Me.Button1 = New System.Windows.Forms.Button()
Me.MainUserControl = New UserControl()
CType(Me.SplitContainerMain, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SplitContainerMain.Panel1.SuspendLayout()
Me.SplitContainerMain.Panel2.SuspendLayout()
Me.SplitContainerMain.SuspendLayout()
Me.SuspendLayout()
'
'SplitContainerMain
'
Me.SplitContainerMain.Dock = System.Windows.Forms.DockStyle.Fill
Me.SplitContainerMain.FixedPanel = System.Windows.Forms.FixedPanel.Panel1
Me.SplitContainerMain.Location = New System.Drawing.Point(0, 0)
Me.SplitContainerMain.Name = "SplitContainerMain"
'
'SplitContainerMain.Panel1
'
Me.SplitContainerMain.Panel1.Controls.Add(Me.Button2)
Me.SplitContainerMain.Panel1.Controls.Add(Me.Button1)
Me.SplitContainerMain.Panel1MinSize = 170
'
'SplitContainerMain.Panel2
'
Me.SplitContainerMain.Panel2.Controls.Add(Me.MainUserControl)
Me.SplitContainerMain.Panel2MinSize = 0
Me.SplitContainerMain.Size = New System.Drawing.Size(784, 561)
Me.SplitContainerMain.SplitterDistance = 170
Me.SplitContainerMain.TabIndex = 0
'
'Button2
'
Me.Button2.Location = New System.Drawing.Point(40, 110)
Me.Button2.Name = "Button2"
Me.Button2.Size = New System.Drawing.Size(75, 23)
Me.Button2.TabIndex = 1
Me.Button2.Text = "Button2"
Me.Button2.UseVisualStyleBackColor = True
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(40, 41)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(75, 23)
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
Me.Button1.UseVisualStyleBackColor = True
'
'MainUserControl
'
Me.MainUserControl.Dock = System.Windows.Forms.DockStyle.Fill
Me.MainUserControl.Location = New System.Drawing.Point(0, 0)
Me.MainUserControl.Name = "MainUserControl"
Me.MainUserControl.Size = New System.Drawing.Size(610, 561)
Me.MainUserControl.TabIndex = 0
'
'MainForm
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.AutoSize = True
Me.ClientSize = New System.Drawing.Size(784, 561)
Me.Controls.Add(Me.SplitContainerMain)
Me.MinimumSize = New System.Drawing.Size(800, 600)
Me.Name = "MainForm"
Me.Tag = ""
Me.Text = "Demo"
Me.SplitContainerMain.Panel1.ResumeLayout(False)
Me.SplitContainerMain.Panel2.ResumeLayout(False)
CType(Me.SplitContainerMain, System.ComponentModel.ISupportInitialize).EndInit()
Me.SplitContainerMain.ResumeLayout(False)
Me.ResumeLayout(False)
End Sub
Friend WithEvents SplitContainerMain As SplitContainer
Friend WithEvents MainUserControl As UserControl
Friend WithEvents Button2 As Button
Friend WithEvents Button1 As Button
End Class
And Here is some screen shots :
UC1UserControl displayed correctly
UC2UserControl displayed correctly
UC2UserControl after spliter moved
There is finally no code in UC1UserControl and UC2UserControl except an Label and and a different backcolor to identifiy the UC.
Thanks
After several hours of testing, logging ,etc...
I have found a solution to this.
I have added a line in the sub SetMinSize :
Private Sub SetMinSize()
Dim borderWidth = Me.Width - Me.ClientSize.Width
Me.MinimumSize = New Size(borderWidth + Me.SplitContainerMain.Panel1.Size.Width + Me.SplitContainerMain.SplitterWidth + Me.MainUserControl.MinimumSize.Width,
borderHeight + Me.MainUserControl.MinimumSize.Height)
Me.SplitContainerMain.Panel2.Size = Me.MainUserControl.Size
End Sub
And now it works. Apparently, when moving the splitter, the right panel of the SplitContainer (SplitContainerMain.Panel2) wasn't resized after the form resized.

How to show menu text in custom ToolStripItem?

Mainform VB.Net:
<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.tsBasket = New System.Windows.Forms.ToolStrip()
Me.tsiFruit = New System.Windows.Forms.ToolStripDropDownButton()
Me.tsBasket.SuspendLayout()
Me.SuspendLayout()
'
'tsBasket
'
Me.tsBasket.Dock = System.Windows.Forms.DockStyle.None
Me.tsBasket.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden
Me.tsBasket.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.tsiFruit})
Me.tsBasket.Location = New System.Drawing.Point(355, 213)
Me.tsBasket.Name = "tsBasket"
Me.tsBasket.Size = New System.Drawing.Size(121, 25)
Me.tsBasket.TabIndex = 5
'
'tsiFruit
'
Me.tsiFruit.ImageTransparentColor = System.Drawing.Color.Magenta
Me.tsiFruit.Name = "tsiFruit"
Me.tsiFruit.Size = New System.Drawing.Size(87, 22)
Me.tsiFruit.Text = "add fruit"
'
'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.tsBasket)
Me.Name = "Form1"
Me.Text = "Form1"
Me.tsBasket.ResumeLayout(False)
Me.tsBasket.PerformLayout()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents tsBasket As ToolStrip
Friend WithEvents tsiFruit As ToolStripDropDownButton
End Class
Form Load:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim men As New TestTool()
men.Text = "showmeplease"
men.Image = Nothing
men.NewProperty = "BO"
Dim men2 As New TestTool()
men2.Text = "showmeplease2"
men2.Image = Nothing
men2.NewProperty = "BO2"
tsiFruit.DropDownItems.Add(men)
tsiFruit.DropDownItems.Add(men2)
AddHandler men.Click, AddressOf tsiType_Click
AddHandler men2.Click, AddressOf tsiType_Click
End Sub
Private Sub tsiType_Click(sender As System.Object, e As System.EventArgs)
Dim MenuItem As TestTool = DirectCast(sender, TestTool)
MessageBox.Show(MenuItem.NewProperty & " " & MenuItem.Text)
End Sub
Custom class:
Public Class TestTool
Inherits ToolStripItem
Private newPropertyValue As String
Public Property NewProperty() As String
Get
Return newPropertyValue
End Get
Set(ByVal value As String)
newPropertyValue = value
End Set
End Property
Sub New()
' This call is required by the designer.
' InitializeComponent()
End Sub
End Class
On my custom class/Usercontrol I am getting :
The designer must create an instance of type 'System.Windows.Forms.ToolStripItem' but it cannot because the type is declared as abstract. and I am not seeing the text appear in the menu items, but the click event works fine.
Is this the correct way to extend(Inherit using OO) a ToolMenuStrip so that I can have a Display value and a Member value, I want to be able to store an object without using .Tag.
Edit:
I am getting when trying to have nested menus:
System.InvalidCastException: 'Unable to cast object of type 'System.Windows.Forms.ToolStripMenuItem' to type 'WindowsApp1.TestTool'.'
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim men As New TestTool()
men.Text = "showmeplease"
men.Image = Nothing
men.NewProperty = "BO"
Dim men2 As New TestTool()
men2.Text = "showmeplease2"
men2.Image = Nothing
men2.NewProperty = "BO2"
tsiFruit.DropDownItems.Add(men)
tsiFruit.DropDownItems.Add(men2)
Dim TypeMenuItem As TestTool = men.DropDownItems.Add("hh")
For Each mInfo As String In Moreinfo
TypeMenuItem.DropDownItems.Add(mInfo, Nothing, AddressOf tsiType_Click)
Next
AddHandler men.Click, AddressOf tsiType_Click
AddHandler men2.Click, AddressOf tsiType_Click
End Sub
Private p_Moreinfo As List(Of String)
Public Property Moreinfo() As List(Of String)
Get
Dim test As New List(Of String)
test.Add("A")
test.Add("B")
Return test
End Get
Set(ByVal value As List(Of String))
p_Moreinfo = value
End Set
End Property
If you enable the Option Strict check (you should), you will find an error with the line below in the Form1_Load event:
' Error: Option Strict On disallows implicit conversions from ToolStrinpItem
' to TestTool.
Dim TypeMenuItem As TestTool = men.DropDownItems.Add("hh")
Because the .DropDownItems.Add(String) overload returns a ToolStripItem and not an object of type TestTool. The .DropDownItems don't inherit the type of the owner item.
' Compiles.
Dim TypeMenuItem As ToolStripItem = men.DropDownItems.Add("hh")
' Compiles.
Dim TypeMenuItem As ToolStripMenuItem = DirectCast(men.DropDownItems.Add("hh"), ToolStripMenuItem)
' Throws System.InvalidCastException.
Dim TypeMenuItem As TestTool = DirectCast(men.DropDownItems.Add("hh"), TestTool)
So, the code in Load event should be like:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim men As New TestTool With {
.Text = "showmeplease",
.NewProperty = "BO"
}
Dim men2 As New TestTool With {
.Text = "showmeplease2",
.NewProperty = "BO2"
}
tsiFruit.DropDownItems.Add(men)
tsiFruit.DropDownItems.Add(men2)
Dim TypeMenuItem As New TestTool() With {.NewProperty = "hh", .Text = "SomeText"}
men.DropDownItems.Add(TypeMenuItem)
For Each mInfo As String In Moreinfo
Dim item = New TestTool With {.NewProperty = mInfo, .Text = "SomeText"}
AddHandler item.Click, AddressOf tsiType_Click
TypeMenuItem.DropDownItems.Add(item)
Next
AddHandler men.Click, AddressOf tsiType_Click
AddHandler men2.Click, AddressOf tsiType_Click
End Sub
Likewise, to avoid throwing exceptions in the tsiType_Click event, just in case:
Private Sub tsiType_Click(sender As Object, e As EventArgs)
Dim item = TryCast(sender, TestTool)
If item IsNot Nothing Then
MessageBox.Show($"{item.NewProperty} {item.Text}")
Else
MessageBox.Show(DirectCast(sender, ToolStripItem).Text)
End If
End Sub
I believe you have modified the TestTool class as #jmcilhinney commented to something like:
Public Class TestTool
Inherits ToolStripMenuItem
Sub New()
MyBase.New
End Sub
Public Property NewProperty As String
End Class

Custom treeview VB.net

I'm looking to create a custom treeview control in VB.net, what I need to do is have a standard treeview control displaying the system file strucure for example, but with an extra icon on the right on the folder/file name that only appears on hover over of the node. So, for instance, if I hover over the folder Sup2 as shown in the pic, then the orange icon appears
I've done some research and from what I can see, I have to override the onpaint event to make this happen but I'm not sure exactly how to do this. I also need to add an onclick event to that new orange icon.
This is not professional but is worth giving a try..
I created a class that inherited from a Treeview control and overrode the constructor - changing the default width and height, setting the DrawMode to TreeViewDrawMode.OwnerDrawText.
Next, I handled the TreeView.DrawNode event, using a PictureBox to display the Image and changing its location based on the currently highlighted item.
I also handled the Click event of the PictureBox.Under that event, You can do whatever you want with the highlighted node.
I used images from My.Resources for ImageList.Images(0) and PictureBox.Image
Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim trv As New MyTreeView
trv.Nodes.Add("Suppliers")
trv.Nodes(0).Nodes.Add("Sup 1")
trv.Nodes(0).Nodes.Add("Sup 2")
trv.Nodes(0).Nodes.Add("Sup 3")
trv.Nodes(0).Nodes.Add("Sup 4")
trv.Nodes(0).Nodes.Add("Sup 5")
Controls.Add(trv)
End Sub
End Class
'Class Starts Here
Public Class MyTreeView
Inherits TreeView
WithEvents myImage As PictureBox
Dim activeItem As TreeNode 'Variable to store active TreeNode
Public Sub New()
MyBase.New() 'Call the base class constructor
'And set some values
Height = 300
Width = 300
Location = New Point(50, 50)
DrawMode = TreeViewDrawMode.OwnerDrawText 'Very neccesary
AddHandler DrawNode, AddressOf MyTreeViewDrawNode
'Add event handlers
AddHandler AfterCollapse, AddressOf MyTreeViewCollapsed
'Set HotTracking event to true to allow for MouseHover
HotTracking = True
ImageList = new ImageList
ImageList.Images.Add(My.Resources.FolderImage)
ImageIndex = 0
Font = New Font(Font.FontFamily, 10)
'Initialize picturebox
myImage = New PictureBox() With
{
.Image = My.Resources.editPencilImage,
.SizeMode = PictureBoxSizeMode.Zoom,
.Size = New Size(10, 10),
.Visible = False
}
Controls.Add(myImage)
End Sub
Private Sub MyTreeViewCollapsed(sender As Object, e As TreeViewEventArgs)
myImage.Visible = False
End Sub
Sub ImageClicked(sender As Object, e As EventArgs) Handles myImage.Click
If (Not activeItem Is Nothing) Then
MessageBox.Show("Clicked Item - " & activeItem.Text)
End If
End Sub
Private Sub MyTreeViewDrawNode(sender As Object, e As DrawTreeNodeEventArgs)
e.DrawDefault = True
If (e.State = TreeNodeStates.Hot) Then
myImage.Visible = True
activeItem = e.Node
Dim tmpSize = TextRenderer.MeasureText(e.Node.Text, Font)
myImage.Location = New Point(e.Node.Bounds.Location.X + tmpSize.Width, e.Node.Bounds.Location.Y)
End If
End Sub
End Class
I think the following example will give you some hints and tips.
Option Explicit On
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Text
Imports System.Runtime.InteropServices
Public Class TreeViewEx
Inherits TreeView
#Region "API"
Private Const TVM_SETEXTENDEDSTYLE As Integer = &H1100 + 44
Private Const TVS_EX_DOUBLEBUFFER As Integer = &H4
<DllImport("user32.dll")>
Private Shared Function SendMessage(ByVal hWnd As IntPtr,
ByVal msg As Integer,
ByVal wp As IntPtr,
ByVal lp As IntPtr) As IntPtr
End Function
#End Region
#Region "Private Fields"
Private ReadOnly RightImage As Bitmap
Private ReadOnly NSF As StringFormat
Private HoverNode As TreeNode
Private RightImageRect As Rectangle
#End Region
#Region "Constructors"
Sub New()
DrawMode = TreeViewDrawMode.OwnerDrawText
RightImage = New Bitmap(My.Resources.Modify)
NSF = New StringFormat With {
.Alignment = StringAlignment.Near,
.LineAlignment = StringAlignment.Center,
.Trimming = StringTrimming.EllipsisCharacter,
.FormatFlags = StringFormatFlags.NoWrap
}
End Sub
#End Region
#Region "Paint"
Protected Overrides Sub OnDrawNode(e As DrawTreeNodeEventArgs)
MyBase.OnDrawNode(e)
If e.Node Is Nothing Then Return
Dim rect As Rectangle = e.Bounds : rect.Inflate(0, 1)
If Not ClientRectangle.IntersectsWith(rect) Then
Return
End If
Dim G As Graphics = e.Graphics
G.SmoothingMode = SmoothingMode.HighQuality
G.TextRenderingHint = TextRenderingHint.ClearTypeGridFit
'Option1: If you want to draw different background color for the selected node.
'If (e.State And TreeNodeStates.Selected) = TreeNodeStates.Selected Then
' Using br As New SolidBrush(Color.LightSteelBlue) '<- suit yourself!
' G.FillRectangle(br, rect)
' End Using
'Else
' Using br As New SolidBrush(If(e.Node.BackColor.Equals(Color.Empty), BackColor, e.Node.BackColor))
' G.FillRectangle(br, rect)
' End Using
'End If
'Option2: If you don't want Option1.
Using br As New SolidBrush(If(e.Node.BackColor.Equals(Color.Empty), BackColor, e.Node.BackColor))
G.FillRectangle(br, rect)
End Using
Using br As New SolidBrush(If(e.Node.ForeColor.Equals(Color.Empty), ForeColor, e.Node.ForeColor))
G.DrawString(e.Node.Text, If(e.Node.NodeFont, Font), br, rect, NSF)
End Using
If ReferenceEquals(e.Node, HoverNode) Then
RightImageRect = New Rectangle(rect.Right + 5,
rect.Y + ((rect.Height - RightImage.Height) / 2),
rect.Height - 4, rect.Height - 4)
G.DrawImage(RightImage,
RightImageRect,
New Rectangle(0, 0, RightImage.Width, RightImage.Height),
GraphicsUnit.Pixel)
End If
End Sub
#End Region
#Region "Other Events"
'You need this to reduce the flickering.
Protected Overrides Sub OnHandleCreated(ByVal e As EventArgs)
SendMessage(
Handle,
TVM_SETEXTENDEDSTYLE,
IntPtr.op_Explicit(TVS_EX_DOUBLEBUFFER),
IntPtr.op_Explicit(TVS_EX_DOUBLEBUFFER)
)
MyBase.OnHandleCreated(e)
End Sub
Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
MyBase.OnMouseMove(e)
Dim node = GetNodeAt(e.Location)
If node IsNot Nothing Then
'Avoid unnecessary Invalidate() calls.
If Not ReferenceEquals(node, HoverNode) Then
HoverNode = node
Invalidate()
End If
Else
'Avoid unnecessary Invalidate() calls.
If HoverNode IsNot Nothing Then
HoverNode = Nothing
Invalidate()
End If
End If
End Sub
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
MyBase.OnMouseDown(e)
If e.Button = MouseButtons.Left AndAlso
RightImageRect.Contains(e.Location) Then
'Notify the container to do something.
OnEditButtonClicked()
End If
End Sub
Protected Overrides Sub OnMouseLeave(e As EventArgs)
MyBase.OnMouseLeave(e)
Invalidate()
End Sub
Protected Overrides Sub Dispose(disposing As Boolean)
MyBase.Dispose(disposing)
If disposing Then
RightImage.Dispose()
NSF.Dispose()
End If
End Sub
#End Region
#Region "Custom Events"
Public Class EditButtonClickArgs
Inherits EventArgs
Public Property Node As TreeNode
Sub New(node As TreeNode)
Me.Node = node
End Sub
End Class
''' <summary>
''' Raised when the right image is clicked.
''' </summary>
Public Event EditButtonClicked As EventHandler(Of EditButtonClickArgs)
''' <summary>
''' Raises the <see cref="EditButtonClicked"/> events.
''' </summary>
Protected Overridable Sub OnEditButtonClicked()
RaiseEvent EditButtonClicked(Me, New EditButtonClickArgs(HoverNode))
End Sub
#End Region
End Class
In the Form that contains the new TreeViewEx control, you can handle the EditButtonClicked to do the necessary:
Public Class Form1
Inherits Form
Private Sub TreeViewEx1_EditButtonClicked(sender As Object, e As TreeViewEx.EditButtonClickArgs) Handles TreeViewEx1.EditButtonClicked
'Do something with the e.Node
End Sub
End Class
And here's a quick demo:
Good luck.

Why is this event handler method being repeatedly called?

The DataGridViewComboBoxColumn control can be difficult to work with. I've been fighting various permutations of this code for two long days, so I've decided to throw in the towel and seek some assistance.
The latest incarnation of weirdness is a ComboBox event handler that fires an increasing number of times for a single user action. Oddly, the rate of increase is an exact doubling of the count just preceding (i.e. 1, 2, 4, 8, 16, 32, 64 etc.)
To start things off, I'll explain what I'm trying to accomplish and also clarify some terminology.
I have a Dictionary(Of Integer, String). In my domain rules, I'm calling its Key property Channel and its Value property Label. I'm mapping each KeyValuePair to a third String value called Target. The Dictionary(Of Integer, String) items are fixed—they exist as a visual aid for the user, so he can easily select the Target from a List(Of String).
I've settled on a DataGridView control to provide this functionality. I'm using three columns, like so:
Note that already-mapped Target list items are displayed in a nearly-invisible color, so as to discourage the user from trying to use them again. (This is where the event handler problem comes in—when an already-mapped Target is selected for mapping to a different Label.)
I'm including my full code base below, but for a quick look here's the event handler that repeats:
Private Sub ComboBox_SelectionChangeCommitted(Sender As ComboBox, e As EventArgs)
' '
' Look for other labels that have already been mapped to this target '
' '
If Me.OtherTargetCells.Any(Function(Cell) Cell.FormattedValue = Sender.Text) Then
If Me.IsInteractiveChange Then
MsgBox("Target [] is already mapped to Label []. If you want to map Target [] to Label [], you must first set Label [] to [Not mapped].", MsgBoxStyle.Exclamation, Me.DataGridView.FindForm.Text)
Me.IsInteractiveChange = False
Sender.SelectedIndex = 0
Me.IsInteractiveChange = True
End If
End If
End Sub
And here's how I'm wiring it all up:
Public Sub New()
Task.Run(Sub()
Dim oHandler As DataGridViewEditingControlShowingEventHandler
While Me.DataGridView Is Nothing
End While
oHandler = New DataGridViewEditingControlShowingEventHandler(AddressOf DataGridView_EditingControlShowing)
RemoveHandler Me.DataGridView.EditingControlShowing, oHandler
AddHandler Me.DataGridView.EditingControlShowing, oHandler
End Sub)
End Sub
Private Sub DataGridView_EditingControlShowing(Sender As DataGridView, e As DataGridViewEditingControlShowingEventArgs)
Dim oComboBox As ComboBox
If TypeOf e.Control Is ComboBox Then
oComboBox = e.Control
oComboBox.DrawMode = DrawMode.OwnerDrawFixed
RemoveHandler oComboBox.DrawItem, New DrawItemEventHandler(AddressOf ComboBox_DrawItem)
AddHandler oComboBox.DrawItem, New DrawItemEventHandler(AddressOf ComboBox_DrawItem)
RemoveHandler oComboBox.SelectionChangeCommitted, New EventHandler(AddressOf ComboBox_SelectionChangeCommitted)
AddHandler oComboBox.SelectionChangeCommitted, New EventHandler(AddressOf ComboBox_SelectionChangeCommitted)
End If
End Sub
The repeat count multiplies when I select an already-mapped Target from a different list than previously (e.g. selecting twice from SCC doesn't increase the count, but selecting from SCC and then Scale does.)
I've tried many, many, many possible solutions for this—too many to list here and most of which I just don't remember—but none with any success.
What can I do to constrain the handler to fire only once for each selection change?
Mapping.TargetsColumn.vb
Namespace Mapping
Public Class TargetsColumn
Inherits DataGridViewComboBoxColumn
Public Sub New()
Task.Run(Sub()
Dim oHandler As DataGridViewEditingControlShowingEventHandler
While Me.DataGridView Is Nothing
End While
oHandler = New DataGridViewEditingControlShowingEventHandler(AddressOf DataGridView_EditingControlShowing)
RemoveHandler Me.DataGridView.EditingControlShowing, oHandler
AddHandler Me.DataGridView.EditingControlShowing, oHandler
End Sub)
End Sub
Private Sub DataGridView_EditingControlShowing(Sender As DataGridView, e As DataGridViewEditingControlShowingEventArgs)
Dim oComboBox As ComboBox
If TypeOf e.Control Is ComboBox Then
oComboBox = e.Control
oComboBox.DrawMode = DrawMode.OwnerDrawFixed
RemoveHandler oComboBox.DrawItem, New DrawItemEventHandler(AddressOf ComboBox_DrawItem)
AddHandler oComboBox.DrawItem, New DrawItemEventHandler(AddressOf ComboBox_DrawItem)
RemoveHandler oComboBox.SelectionChangeCommitted, New EventHandler(AddressOf ComboBox_SelectionChangeCommitted)
AddHandler oComboBox.SelectionChangeCommitted, New EventHandler(AddressOf ComboBox_SelectionChangeCommitted)
End If
End Sub
Private Sub ComboBox_DrawItem(Sender As ComboBox, e As DrawItemEventArgs)
Dim sThisTarget As String
Dim oForeColor As Color
Dim _
iSeparatorBottom,
iSeparatorRight,
iSeparatorLeft As Integer
Dim _
oSeparatorStart,
oSeparatorStop As Point
sThisTarget = DirectCast(Me.Items(e.Index), Target).Value
iSeparatorBottom = e.Bounds.Bottom - 2
iSeparatorRight = e.Bounds.Right
iSeparatorLeft = e.Bounds.Left
e.DrawBackground()
If e.Index = 0 Then
oSeparatorStart = New Point(iSeparatorLeft, iSeparatorBottom)
oSeparatorStop = New Point(iSeparatorRight, iSeparatorBottom)
oForeColor = SystemColors.HotTrack
e.Graphics.FillRectangle(SystemBrushes.Control, e.Bounds)
e.Graphics.DrawLine(SystemPens.ControlDark, oSeparatorStart, oSeparatorStop)
Else
If Me.OtherTargets.Contains(sThisTarget) Then
oForeColor = SystemColors.ControlLight
Else
oForeColor = e.ForeColor
End If
End If
Using oBrush As New SolidBrush(oForeColor)
e.Graphics.DrawString(sThisTarget, e.Font, oBrush, e.Bounds)
End Using
If e.State.HasFlag(DrawItemState.Focus) Then e.DrawFocusRectangle()
Me.DataGridView.FindForm.Text = sThisTarget
End Sub
Private Sub ComboBox_SelectionChangeCommitted(Sender As ComboBox, e As EventArgs)
' '
' Look for other labels that have already been mapped to this target '
' '
If Me.OtherTargetCells.Any(Function(Cell) Cell.FormattedValue = Sender.Text) Then
If Me.IsInteractiveChange Then
MsgBox("Target [] is already mapped to Label []. If you want to map Target [] to Label [], you must first set Label [] to [Not mapped].", MsgBoxStyle.Exclamation, Me.DataGridView.FindForm.Text)
Me.IsInteractiveChange = False
Sender.SelectedIndex = 0
Me.IsInteractiveChange = True
End If
End If
End Sub
Private ReadOnly Property OtherTargets As List(Of String)
Get
Return Me.OtherTargetCells.Select(Function(Cell) DirectCast(Cell.FormattedValue, String)).ToList
End Get
End Property
Private ReadOnly Property CurrentTargetCell As DataGridViewCell
Get
Return Me.AllTargetCells(Me.DataGridView.CurrentRow.Index)
End Get
End Property
Private ReadOnly Property AllTargetCells As List(Of DataGridViewCell)
Get
Dim oAllCells As IEnumerable(Of DataGridViewCell)
Dim oRows As IEnumerable(Of DataGridViewRow)
oRows = Me.DataGridView.Rows.Cast(Of DataGridViewRow)
oAllCells = oRows.SelectMany(Function(Row) Row.Cells.Cast(Of DataGridViewCell))
Return oAllCells.Where(Function(Cell) TypeOf Cell Is DataGridViewComboBoxCell).ToList
End Get
End Property
Private ReadOnly Property OtherTargetCells As List(Of DataGridViewCell)
Get
Return Me.AllTargetCells.Where(Function(Cell) Cell.RowIndex <> Me.RowIndex).ToList
End Get
End Property
Private ReadOnly Property RowIndex As Integer
Get
Return Me.DataGridView.CurrentRow.Index
End Get
End Property
Private IsInteractiveChange As Boolean = True
Private ReadOnly ComboBoxes As New Dictionary(Of Integer, ComboBox)
End Class
End Namespace
Form1.vb
Public Class Form1
Inherits Form
Public Sub New()
Dim oColTargets As Mapping.TargetsColumn
Dim oTargets As IEnumerable(Of String)
Dim oQuery As Func(Of Target, Boolean)
Dim sChannel As String
Dim oTarget As Target
Dim oMaps As Dictionary(Of Integer, String)
Dim oMap As Map
Dim _
oColChannels,
oColLabels As DataGridViewTextBoxColumn
Me.InitializeComponent()
Me.Targets.Add(New Target("Not mapped"))
sChannel = String.Empty
oQuery = Function(Target) Target.Value = sChannel
'oTargets = Reader.Client.Create.Call(Function(Service As Reader.IService) Service.GetChannelTargets)'
oTargets = New List(Of String) From {"Scale", "SCC", "CO", "O2"}
oTargets.ToList.ForEach(Sub(Target)
Me.Targets.Add(New Target(Target))
End Sub)
'oMaps = Reader.Client.Create.Call(Function(Service As Reader.IService) Service.GetChannelMaps)'
oMaps = New Dictionary(Of Integer, String) From {{3, "Test"}, {7, "SCC"}, {8, "Scale"}, {9, "CO"}, {10, "O2"}}
oMaps.ToList.ForEach(Sub(Map)
sChannel = Map.Value
If Me.Targets.Any(oQuery) Then
oTarget = Me.Targets.Single(oQuery)
Else
oTarget = Me.Targets.First
End If
oMap = New Map With {
.Channel = Map.Key,
.Label = Map.Value,
.Target = oTarget
}
Me.Maps.Add(oMap)
End Sub)
oColChannels = New DataGridViewTextBoxColumn With {
.DataPropertyName = NameOf(Map.Channel),
.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader,
.HeaderText = NameOf(Map.Channel),
.ReadOnly = True,
.Name = NameOf(oColChannels)
}
oColLabels = New DataGridViewTextBoxColumn With {
.DataPropertyName = NameOf(Map.Label),
.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader,
.HeaderText = NameOf(Map.Label),
.ReadOnly = True,
.Name = NameOf(oColLabels)
}
oColTargets = New Mapping.TargetsColumn With {
.DataPropertyName = NameOf(Map.Target),
.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
.DisplayMember = NameOf(Target.Value),
.ValueMember = NameOf(Target.Self),
.HeaderText = NameOf(Map.Target),
.DataSource = Me.Targets,
.Name = NameOf(oColTargets)
}
dgvMapping.AutoGenerateColumns = False
dgvMapping.Columns.AddRange({oColChannels, oColLabels, oColTargets})
For Each oColumn As DataGridViewColumn In dgvMapping.Columns
oColumn.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
If oColumn.Index = 0 Then
oColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
End If
Next
dgvMapping.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize
dgvMapping.DataSource = New BindingList(Of Map)(Me.Maps)
If dgvMapping.RowCount = 0 Then
dgvMapping.Height = 150
Else
dgvMapping.Height = ((dgvMapping.RowCount + 0) * dgvMapping.Rows(0).Height) + dgvMapping.ColumnHeadersHeight
End If
End Sub
Private Sub Form1_FormClosing(Sender As Form1, e As FormClosingEventArgs) Handles Me.FormClosing
Dim oPolicy As Target = Me.Maps.First.Target
Dim sName As String = Me.Maps.First.Channel
End Sub
Private Sub _dgvMapping_DataError(Sender As DataGridView, e As DataGridViewDataErrorEventArgs) Handles dgvMapping.DataError
MsgBox(e.Exception.Message, MsgBoxStyle.Critical, Me.Text)
End Sub
Private Targets As New BindingList(Of Target)
Private Maps As New List(Of Map)
End Class
Public Class Map
Public Property Channel As Integer
Public Property Label As String
Public Property Target As Target
End Class
Public Class Target
Public Sub New(Target As String)
Me.Value = Target
End Sub
Public ReadOnly Property Self As Target
Get
Return Me
End Get
End Property
Public ReadOnly Property Value As String
End Class
Form1.Designer.vb
<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.dgvMapping = New System.Windows.Forms.DataGridView()
CType(Me.dgvMapping, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
' '
'dgvMapping'
' '
Me.dgvMapping.AllowUserToAddRows = False
Me.dgvMapping.AllowUserToDeleteRows = False
Me.dgvMapping.AllowUserToOrderColumns = True
Me.dgvMapping.AllowUserToResizeColumns = False
Me.dgvMapping.AllowUserToResizeRows = False
Me.dgvMapping.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.dgvMapping.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter
Me.dgvMapping.Location = New System.Drawing.Point(12, 12)
Me.dgvMapping.Name = "dgvMapping"
Me.dgvMapping.RowHeadersVisible = False
Me.dgvMapping.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect
Me.dgvMapping.Size = New System.Drawing.Size(250, 150)
Me.dgvMapping.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.dgvMapping)
Me.Font = New System.Drawing.Font("Segoe UI", 8.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.Name = "Form1"
Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
Me.Text = "Form1"
CType(Me.dgvMapping, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
Friend WithEvents dgvMapping As DataGridView
End Class
Fixed.
I was instantiating a new event handler object for each AddHandler/RemoveHandler call.
When I removed the instantiations and used simple expressions instead, the ComboBoxes started behaving correctly.
Public Sub New()
Task.Run(Sub()
While Me.DataGridView Is Nothing
End While
RemoveHandler Me.DataGridView.EditingControlShowing, AddressOf DataGridView_EditingControlShowing
AddHandler Me.DataGridView.EditingControlShowing, AddressOf DataGridView_EditingControlShowing
End Sub)
End Sub
Private Sub DataGridView_EditingControlShowing(Sender As Object, e As DataGridViewEditingControlShowingEventArgs)
Dim oComboBox As ComboBox
If TypeOf e.Control Is ComboBox Then
oComboBox = e.Control
oComboBox.DrawMode = DrawMode.OwnerDrawFixed
RemoveHandler oComboBox.DrawItem, AddressOf ComboBox_DrawItem
AddHandler oComboBox.DrawItem, AddressOf ComboBox_DrawItem
RemoveHandler oComboBox.SelectionChangeCommitted, AddressOf ComboBox_SelectionChangeCommitted
AddHandler oComboBox.SelectionChangeCommitted, AddressOf ComboBox_SelectionChangeCommitted
End If
End Sub
I had to relax the Sender parameter types to Object in the event handler methods, but that didn't carry any serious consequence.
Private Sub DataGridView_EditingControlShowing(Sender As Object, e As DataGridViewEditingControlShowingEventArgs)
End Sub
Private Sub ComboBox_DrawItem(Sender As Object, e As DrawItemEventArgs)
End Sub
Private Sub ComboBox_SelectionChangeCommitted(Sender As Object, e As EventArgs)
End Sub
For what it's worth: I generally prefer to constrain the Sender parameter to the calling type, for more efficient coding, but that wasn't possible in this case. Nevertheless, the only impact was the need to cast the Sender in one place in one method body:
Dim oQuery = Function(Cell) Cell.FormattedValue = DirectCast(Sender, ComboBox).Text
It works as expected now.

MsgBox not displayed on 1st click after changing content in textbox

I am trying to learn by creating this basic form. where the user is asked a password and username
currently both are text field and insecure.
the problem is that whenever i change any of the 2 fields the 1st click does not work.
the code works fine from 2nd click.
edit- there is no problem till the user and password are wrong.
here is the snippet
Private Sub BtnLogIn_Click(sender As Object, e As EventArgs) Handles BtnLogIn.Click
If (TxtUsername.Text = "shikhar" And TxtPassword.Text = "pass") Then
'goto next screen & remove message box'
MsgBox("correct Username or Password", MsgBoxStyle.OkOnly + MsgBoxStyle.Information, "login Completed")
Else
MsgBox("Incorrect Username or Password", MsgBoxStyle.OkOnly + MsgBoxStyle.Exclamation, "login error")
End If
End Sub
this is the overall file-
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Login
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.lblUsername = New System.Windows.Forms.Label()
Me.lblPassword = New System.Windows.Forms.Label()
Me.TxtUsername = New System.Windows.Forms.TextBox()
Me.TxtPassword = New System.Windows.Forms.TextBox()
Me.BtnLogIn = New System.Windows.Forms.Button()
Me.SuspendLayout()
'
'lblUsername
'
Me.lblUsername.AutoSize = True
Me.lblUsername.Location = New System.Drawing.Point(69, 84)
Me.lblUsername.Name = "lblUsername"
Me.lblUsername.Size = New System.Drawing.Size(55, 13)
Me.lblUsername.TabIndex = 0
Me.lblUsername.Text = "Username"
'
'lblPassword
'
Me.lblPassword.AutoSize = True
Me.lblPassword.Location = New System.Drawing.Point(69, 130)
Me.lblPassword.Name = "lblPassword"
Me.lblPassword.Size = New System.Drawing.Size(53, 13)
Me.lblPassword.TabIndex = 1
Me.lblPassword.Text = "Password"
'
'TxtUsername
'
Me.TxtUsername.Location = New System.Drawing.Point(178, 77)
Me.TxtUsername.Name = "TxtUsername"
Me.TxtUsername.Size = New System.Drawing.Size(199, 20)
Me.TxtUsername.TabIndex = 2
'
'TxtPassword
'
Me.TxtPassword.Location = New System.Drawing.Point(178, 123)
Me.TxtPassword.Name = "TxtPassword"
Me.TxtPassword.Size = New System.Drawing.Size(198, 20)
Me.TxtPassword.TabIndex = 3
'
'BtnLogIn
'
Me.BtnLogIn.Location = New System.Drawing.Point(181, 172)
Me.BtnLogIn.Name = "BtnLogIn"
Me.BtnLogIn.Size = New System.Drawing.Size(164, 45)
Me.BtnLogIn.TabIndex = 4
Me.BtnLogIn.Text = "Log In"
Me.BtnLogIn.UseVisualStyleBackColor = True
'
'Login
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(474, 261)
Me.Controls.Add(Me.BtnLogIn)
Me.Controls.Add(Me.TxtPassword)
Me.Controls.Add(Me.TxtUsername)
Me.Controls.Add(Me.lblPassword)
Me.Controls.Add(Me.lblUsername)
Me.Name = "Login"
Me.Text = "Login"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents lblUsername As System.Windows.Forms.Label
Friend WithEvents lblPassword As System.Windows.Forms.Label
Friend WithEvents TxtUsername As System.Windows.Forms.TextBox
Friend WithEvents TxtPassword As System.Windows.Forms.TextBox
Friend WithEvents BtnLogIn As System.Windows.Forms.Button
End Class