How to make LinearLayout in Visual Basic (visual studio 2013) - vb.net

(this is not related to VB6)
like above, I want to make a 'textbox' control between separated 'label' controls.
I used method to load those three controls (two labels and one textbox), but I cannot precisely locate the textbox and the following label.
In the application, there will be more than hundreds of sentences with almost the same number of blanks(textbox), so the perfect lining is required.
So, is there any good method to do that?
Thank you!

You can make a class that inherits from Panel and includes two Labels and a Textbox that get automatically realigned. I did something like that to get you started. Just paste the code into your project, recompile once and you can add these to your Form from the Toolbox (or create them dynamically of course). This is nowhere complete. You should make properties for the fonts for example and additional events based on your needs but you get my idea I think.
Public Class ctrlBlankSentence
Inherits Panel
Private WithEvents lblLeft As Label 'The left part of the sentence
Private WithEvents tbBlank As TextBox 'The blank text
Private WithEvents lblRight As Label 'The right part of the sentence
Public Event BlankTextChanged() 'Use events to react to user input
Private _Spacing As Integer
''' <summary>
''' Determines the distance between the labels and the textbox
''' </summary>
Public Property Spacing As Integer
Get
Return _Spacing
End Get
Set(value As Integer)
_Spacing = value
DoreAlign()
End Set
End Property
Private _TextboxWidth As Integer
''' <summary>
''' Determines the width of the textbox
''' </summary>
Public Property TextboxWidth As Integer
Get
Return _TextboxWidth
End Get
Set(value As Integer)
_TextboxWidth = value
DoreAlign()
End Set
End Property
Private _AutosizeControl As Boolean
''' <summary>
''' Determines if the panel is automatically resized.
''' </summary>
Public Property AutosizeControl As Boolean
Get
Return _AutosizeControl
End Get
Set(value As Boolean)
_AutosizeControl = value
DoreAlign()
End Set
End Property
''' <summary>
''' Used to get or set the left part of the sentence
''' </summary>
Public Property LeftText As String
Get
Return lblLeft.Text
End Get
Set(value As String)
lblLeft.Text = value
DoreAlign()
End Set
End Property
''' <summary>
''' Used to set the right part of the sentence
''' </summary>
Public Property RightText As String
Get
Return lblRight.Text
End Get
Set(value As String)
lblRight.Text = value
DoreAlign()
End Set
End Property
''' <summary>
''' Used to get or set the user input
''' </summary>
Public Property BlankText As String
Get
Return tbBlank.Text
End Get
Set(value As String)
tbBlank.Text = value
RaiseEvent BlankTextChanged()
End Set
End Property
#Region "Constructor"
Public Sub New()
lblLeft = New Label With {.AutoSize = True, .Text = "Left Text"}
lblRight = New Label With {.AutoSize = True, .Text = "Right Text"}
tbBlank = New TextBox
Spacing = 3
TextboxWidth = 100
AutosizeControl = True
Me.Controls.Add(lblLeft)
Me.Controls.Add(lblRight)
Me.Controls.Add(tbBlank)
DoreAlign()
End Sub
#End Region
#Region "The method the realigns the controls"
Private Sub DoreAlign()
lblLeft.Left = 0
tbBlank.Left = lblLeft.Right + Spacing
tbBlank.Width = TextboxWidth
lblRight.Left = tbBlank.Right + Spacing
If AutosizeControl Then
Me.Width = lblRight.Right
Me.Height = tbBlank.Height
End If
lblRight.Top = CInt(Me.Height / 2 - lblRight.Height / 2)
lblLeft.Top = lblRight.Top
End Sub
#End Region
Private Sub thisTextChanged() Handles tbBlank.TextChanged
RaiseEvent BlankTextChanged()
End Sub
End Class

Related

Adding a progress bar to show how much percentage of form had been loaded

I've a form having certain lines of code on the form_load event and thus it takes some time to be shown. I want to add a progress bar to show how much percentage of form has been loaded. How can I do so ..?
In short:- Like while browsing the web pages the progress as shown in web browser indicate the value of page has been loaded. I want to do so in vb.net.
How can I do so .?
You'll need to move your long running code into the form's .Shown event handler.
I would suggest adding a StatusStrip to your form and add a ToolStripProgressBar to that. I did this in a program I wrote and used the following bit of code work on it.
It's all pretty self explanatory :-)
''' <summary>
''' Sets minimum and maximum values for ToolStripProgressBar and shows it
''' </summary>
''' <param name="min">Minimum Value</param>
''' <param name="max">Maximum Value</param>
''' <param name="labeltext">Text to show in ToolStripLabel</param>
Private Sub SetAndShowProgressBar(min As Integer, max As Integer, labeltext As String)
ToolStripStatusLabel1.Text = labeltext
ToolStripProgressBar1.Minimum = min
ToolStripProgressBar1.Maximum = max + 5
ToolStripProgressBar1.Value = 1
ToolStripProgressBar1.Visible = True
StatusStrip1.Update()
End Sub
''' <summary>
''' Hides ToolStripProgressBar
''' </summary>
Private Sub HideProgressBar()
ToolStripStatusLabel1.Text = ""
ToolStripProgressBar1.Visible = False
StatusStrip1.Update()
End Sub
Private Delegate Sub incprogressbarDelegate()
Private Sub IncrementProgressBar()
If Me.InvokeRequired Then
Dim d As New incprogressbarDelegate(AddressOf IncrementProgressBar)
Me.Invoke(d, New Object())
Else
Me.ToolStripProgressBar1.Value += 1
StatusStrip1.Update()
End If
End Sub
Private Delegate Sub SetProgressBarDelegate(i As Integer)
Private Sub SetProgressBarValue(i As Integer)
If Me.InvokeRequired Then
Dim d As New SetProgressBarDelegate(AddressOf SetProgressBarValue)
Me.Invoke(d, New Object() {i})
Else
Me.ToolStripProgressBar1.Value = i
End If
End Sub

How to read data from serial port in vb.net?

I made a class and there is this sub named SendUSSD, when this is called it sends a ussd code like *123# to a COM port where a gsm mobile is connected. This ussd is supposed to return the mobile balance.
If IsOpen = True Then 'checks if the port is open
SMSPort.WriteLine("AT+CUSD=1,""*123#""" vbCr) 'this sends the ussd code
Form1.TextBox2.Text = SMSPort.ReadLine().ToString() 'this shows the response
End If
Now the problem is sometimes I get the full response like "Your current balance is so and so". But, most of the time I get a part of the message like "Your curr". My guess is that it takes some time to get the response, so how do I make this Form1.TextBox2.Text = SMSPort.ReadLine().ToString() line wait until the last character which is a full-stop to appear and then execute the line?
im using this class to connect com ports.
'connect like this
Public comm As New CommunicationManager
comm.Parity = "None"
comm.StopBits = "One"
comm.DataBits = "8"
comm.BaudRate = "38400"
comm.PortName = comport_ismi
comm.OpenPort()
and the class
Imports System.Text
Imports System.Drawing
Imports System.IO.Ports
Imports System.Windows.Forms
Public Class CommunicationManager
#Region "Manager Enums"
''' <summary>
''' enumeration to hold our transmission types
''' </summary>
Public Enum TransmissionType
Text
Hex
End Enum
''' <summary>
''' enumeration to hold our message types
''' </summary>
Public Enum MessageType
Incoming
Outgoing
Normal
Warning
[Error]
End Enum
#End Region
#Region "Manager Variables"
'property variables
Private _baudRate As String = String.Empty
Private _parity As String = String.Empty
Private _stopBits As String = String.Empty
Private _dataBits As String = String.Empty
Private _portName As String = String.Empty
Private _transType As TransmissionType
Private _displayWindow As RichTextBox
'global manager variables
Private MessageColor As Color() = {Color.Blue, Color.Green, Color.Black, Color.Orange, Color.Red}
Private comPort As New SerialPort()
#End Region
#Region "Manager Properties"
''' <summary>
''' Property to hold the BaudRate
''' of our manager class
''' </summary>
Public Property BaudRate() As String
Get
Return _baudRate
End Get
Set(value As String)
_baudRate = value
End Set
End Property
''' <summary>
''' property to hold the Parity
''' of our manager class
''' </summary>
Public Property Parity() As String
Get
Return _parity
End Get
Set(value As String)
_parity = value
End Set
End Property
''' <summary>
''' property to hold the StopBits
''' of our manager class
''' </summary>
Public Property StopBits() As String
Get
Return _stopBits
End Get
Set(value As String)
_stopBits = value
End Set
End Property
''' <summary>
''' property to hold the DataBits
''' of our manager class
''' </summary>
Public Property DataBits() As String
Get
Return _dataBits
End Get
Set(value As String)
_dataBits = value
End Set
End Property
''' <summary>
''' property to hold the PortName
''' of our manager class
''' </summary>
Public Property PortName() As String
Get
Return _portName
End Get
Set(value As String)
_portName = value
End Set
End Property
''' <summary>
''' property to hold our TransmissionType
''' of our manager class
''' </summary>
Public Property CurrentTransmissionType() As TransmissionType
Get
Return _transType
End Get
Set(value As TransmissionType)
_transType = value
End Set
End Property
''' <summary>
''' property to hold our display window
''' value
''' </summary>
Public Property DisplayWindow() As RichTextBox
Get
Return _displayWindow
End Get
Set(value As RichTextBox)
_displayWindow = value
End Set
End Property
#End Region
#Region "Manager Constructors"
''' <summary>
''' Constructor to set the properties of our Manager Class
''' </summary>
''' <param name="baud">Desired BaudRate</param>
''' <param name="par">Desired Parity</param>
''' <param name="sBits">Desired StopBits</param>
''' <param name="dBits">Desired DataBits</param>
''' <param name="name">Desired PortName</param>
Public Sub New(baud As String, par As String, sBits As String, dBits As String, name As String, rtb As RichTextBox)
_baudRate = baud
_parity = par
_stopBits = sBits
_dataBits = dBits
_portName = name
_displayWindow = rtb
'now add an event handler
AddHandler comPort.DataReceived, New SerialDataReceivedEventHandler(AddressOf comPort_DataReceived)
End Sub
''' <summary>
''' Comstructor to set the properties of our
''' serial port communicator to nothing
''' </summary>
Public Sub New()
_baudRate = String.Empty
_parity = String.Empty
_stopBits = String.Empty
_dataBits = String.Empty
_portName = comport_ismi
_displayWindow = Nothing
'add event handler
AddHandler comPort.DataReceived, New SerialDataReceivedEventHandler(AddressOf comPort_DataReceived)
End Sub
#End Region
#Region "WriteData"
Public Sub WriteData(msg As String)
Select Case CurrentTransmissionType
Case TransmissionType.Text
'first make sure the port is open
'if its not open then open it
If Not (comPort.IsOpen = True) Then
comPort.Open()
End If
'send the message to the port
comPort.Write(msg)
'display the message
DisplayData(MessageType.Outgoing, msg & Convert.ToString(vbLf))
Exit Select
Case TransmissionType.Hex
Try
'convert the message to byte array
Dim newMsg As Byte() = HexToByte(msg)
'send the message to the port
comPort.Write(newMsg, 0, newMsg.Length)
'convert back to hex and display
DisplayData(MessageType.Outgoing, ByteToHex(newMsg) & Convert.ToString(vbLf))
Catch ex As FormatException
'display error message
DisplayData(MessageType.[Error], ex.Message)
Finally
_displayWindow.SelectAll()
End Try
Exit Select
Case Else
'first make sure the port is open
'if its not open then open it
If Not (comPort.IsOpen = True) Then
comPort.Open()
End If
'send the message to the port
comPort.Write(msg)
'display the message
DisplayData(MessageType.Outgoing, msg & Convert.ToString(vbLf))
Exit Select
End Select
End Sub
#End Region
#Region "HexToByte"
''' <summary>
''' method to convert hex string into a byte array
''' </summary>
''' <param name="msg">string to convert</param>
''' <returns>a byte array</returns>
Private Function HexToByte(msg As String) As Byte()
'remove any spaces from the string
msg = msg.Replace(" ", "")
'create a byte array the length of the
'divided by 2 (Hex is 2 characters in length)
Dim comBuffer As Byte() = New Byte(msg.Length / 2 - 1) {}
'loop through the length of the provided string
For i As Integer = 0 To msg.Length - 1 Step 2
'convert each set of 2 characters to a byte
'and add to the array
comBuffer(i / 2) = CByte(Convert.ToByte(msg.Substring(i, 2), 16))
Next
'return the array
Return comBuffer
End Function
#End Region
#Region "ByteToHex"
''' <summary>
''' method to convert a byte array into a hex string
''' </summary>
''' <param name="comByte">byte array to convert</param>
''' <returns>a hex string</returns>
Private Function ByteToHex(comByte As Byte()) As String
'create a new StringBuilder object
Dim builder As New StringBuilder(comByte.Length * 3)
'loop through each byte in the array
For Each data As Byte In comByte
'convert the byte to a string and add to the stringbuilder
builder.Append(Convert.ToString(data, 16).PadLeft(2, "0"c).PadRight(3, " "c))
Next
'return the converted value
Return builder.ToString().ToUpper()
End Function
#End Region
#Region "DisplayData"
''' <summary>
''' method to display the data to & from the port
''' on the screen
''' </summary>
''' <param name="type">MessageType of the message</param>
''' <param name="msg">Message to display</param>
<STAThread> _
Private Sub DisplayData(type As MessageType, msg As String)
'_displayWindow.Invoke(New EventHandler(Sub()
' _displayWindow.SelectedText = String.Empty
' _displayWindow.SelectionFont = New Font(_displayWindow.SelectionFont, FontStyle.Bold)
' _displayWindow.SelectionColor = MessageColor(CInt(type))
' _displayWindow.AppendText(msg)
' _displayWindow.ScrollToCaret()
' End Sub))
End Sub
#End Region
#Region "OpenPort"
Public Function OpenPort() As Boolean
Try
'first check if the port is already open
'if its open then close it
If comPort.IsOpen = True Then
comPort.Close()
End If
'set the properties of our SerialPort Object
comPort.BaudRate = Integer.Parse(_baudRate)
'BaudRate
comPort.DataBits = Integer.Parse(_dataBits)
'DataBits
comPort.StopBits = DirectCast([Enum].Parse(GetType(StopBits), _stopBits), StopBits)
'StopBits
comPort.Parity = DirectCast([Enum].Parse(GetType(Parity), _parity), Parity)
'Parity
comPort.PortName = _portName
'PortName
'now open the port
comPort.Open()
'display message
DisplayData(MessageType.Normal, "Port AÇILDI: " + DateTime.Now + vbLf)
'return true
Return True
Catch ex As Exception
DisplayData(MessageType.[Error], ex.Message)
Return False
End Try
End Function
#End Region
#Region "ClosePort"
Public Function ClosePort() As Boolean
Try
'first check if the port is already open
'if its open then close it
If comPort.IsOpen = True Then
comPort.Close()
End If
'display message
DisplayData(MessageType.Normal, "Port KAPANDI: " + DateTime.Now + vbLf)
'return true if port is closed
If comPort.IsOpen = False Then
Return True
End If
DisplayData(MessageType.Normal, "Kapatmada hata oluştu" & vbLf)
Return False
Catch ex As Exception
DisplayData(MessageType.[Error], ex.Message)
Return False
End Try
End Function
#End Region
#Region "SetParityValues"
Public Sub SetParityValues(obj As Object)
For Each str As String In [Enum].GetNames(GetType(Parity))
DirectCast(obj, ComboBox).Items.Add(str)
Next
End Sub
#End Region
#Region "SetStopBitValues"
Public Sub SetStopBitValues(obj As Object)
For Each str As String In [Enum].GetNames(GetType(StopBits))
DirectCast(obj, ComboBox).Items.Add(str)
Next
End Sub
#End Region
#Region "SetPortNameValues"
Public Sub SetPortNameValues(obj As Object)
For Each str As String In SerialPort.GetPortNames()
DirectCast(obj, ComboBox).Items.Add(str)
Next
End Sub
#End Region
#Region "comPort_DataReceived"
''' <summary>
''' method that will be called when theres data waiting in the buffer
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub comPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs)
'determine the mode the user selected (binary/string)
Select Case CurrentTransmissionType
'user chose string
Case TransmissionType.Text
'read data waiting in the buffer
Dim msg As String = comPort.ReadExisting()
'display the data to the user
DisplayData(MessageType.Incoming, msg)
' + "\n"); **************
Exit Select
'user chose binary
Case TransmissionType.Hex
'retrieve number of bytes in the buffer
Dim bytes As Integer = comPort.BytesToRead
'create a byte array to hold the awaiting data
Dim comBuffer As Byte() = New Byte(bytes - 1) {}
'read the data and store it
comPort.Read(comBuffer, 0, bytes)
'display the data to the user
DisplayData(MessageType.Incoming, ByteToHex(comBuffer))
' + "\n");
Exit Select
Case Else
'read data waiting in the buffer
Dim str As String = comPort.ReadExisting()
'display the data to the user
DisplayData(MessageType.Incoming, str)
' + "\n");
Exit Select
End Select
End Sub
#End Region
End Class
I guess you are using the DataReceived event, if so, you can just take the data and split it by the lastIndexOf(Enviroment.NewLine).
you will have two part the first one is a string with some amount of lines and the second one is a string that contain no more lines.
You can take the first part and split it by new line and even create a new event (LineReceived).
for the second part(the part after the lastIndexOf(Enviroment.NewLine)) of the data just concatenate it to the beginning of the data that will arrive the next time.
Try setting comm.Newline. Probably should be vbCR.

Nested class & readonly properties

Outside the class I'd like to be able to access CCTV.Camera.Brightness property as ReadOnly, but methods within the CCTV class should be able to modify the Brightness property. Please can you advise on how to achieve this?
I think I need to add an Interface that exposes some properties and hides others, but I'm not sure of the implementation. [Note the constructor and main sub are obviously contrived for this example and testing].
Public Class CCTV
Public Class Camera
Public Property Name as String
Public Property Brightness as Integer
End Class
Dim cameras as New Dictionary(Of String, Camera)
Public Sub New()
Dim cam As New Camera
cam.Name = "driveway"
cam.Brightness = 5
cameras.Add(cam.Name, cam)
End Sub
Public Sub ChangeBrightness(value as Integer)
cameras("driveway").Brightness = value
End Sub
End Class
Sub main()
Dim MyCCTV = new CCTV
MyCCTV.ChangeBrightness(10)
if MyCCTV("driveway").Brightness = 10 then Console.Write("Brightness is 10")
End Sub
Get getter and the setter of a property can have different accessibility modifiers. In this case you want Brightness to be readable by everybody but only the code you trust should be able to write it. You do so like this:
Public Class Camera
Private _brightness As Integer
Public Property Brightness As Integer
Get
Return _brightness
End Get
Friend Set(value As Integer)
_brightness = Value
End Set
End Property
'' etc...
End Class
Note the added Friend keyword, it limits access to the code in the same project that Camera class is a part of. It can also be Private or Protected if you want to limit access to only code inside the Camera class or its derived classes.
no interface is need in this case.You simply have to create your property as readonly.when you set the property as readonly assume that the value will stored within a private variable and at that point should be better pass it or to a method or to the subnew using overloads methods let me show you an example:
Public Class CCTV
Public Class Camera
Private _Name As String
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
Private _Brightness As String
Public ReadOnly Property Brightness() As String
Get
Return _Brightness
End Get
End Property
''' <summary>
''' Defautl sub new method
''' </summary>
''' <remarks></remarks>
Sub New()
End Sub
''' <summary>
''' second overload
''' </summary>
''' <param name="cameraName"></param>
''' <param name="brightness"></param>
''' <remarks></remarks>
Sub New(ByVal cameraName As String, ByVal brightness As Integer)
Me.Name = cameraName
Me._Brightness = brightness
End Sub
''' <summary>
''' Change brigthness
''' </summary>
''' <param name="value"></param>
''' <remarks></remarks>
Public Sub setUpCameraBrightness(ByVal value As Integer)
'take care to use private varibale so it will reflcet changes into propetry readonly
Me._Brightness = value
End Sub
End Class
Dim cameras As New Dictionary(Of String, Camera)
Public Sub New()
'two differnet approach
'first overaload:
Dim cam As New Camera()
cam.Name = "yourcamname"
cam.setUpCameraBrightness(10)
cameras.Add(cam.Name, cam)
''second approch declarative value:
Dim cam2 As New Camera("yourcamname", 10)
cameras.Add(cam2.Name, cam2)
End Sub
Public Sub ChangeBrightness(value As Integer)
cameras("driveway").setUpCameraBrightness(100)
End Sub
End Class
Sub main()
Dim MyCCTV = New CCTV
MyCCTV.ChangeBrightness(10)
If MyCCTV("driveway").Brightness = 10 Then Console.Write("Brightness is 10")
End Sub

Force datagridviewcell that host a numeric updown revert it changed on escape key press

I'm creating a datagridviewcell that host a numeric updown control. Everything went fine except one thing. I can't revert changed on escape key press like textboxcell or comboboxcell. My datagridviewcell was created base on this example. So anyone have any idea how to revert numeric updown cell to previous value on escape key press?
NumericColumn class:
Imports System
Imports System.Windows.Forms
Public Class NumericColumn
Inherits DataGridViewColumn
''' <summary>
''' Get, set numeric control min value
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property MinValue() As Decimal
Get
Return CType(MyBase.CellTemplate, NumericCell).MinValue
End Get
Set(ByVal value As Decimal)
CType(MyBase.CellTemplate, NumericCell).MinValue = value
End Set
End Property
''' <summary>
''' Get, set numeric control max value
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property MaxValue() As Decimal
Get
Return CType(MyBase.CellTemplate, NumericCell).MaxValue
End Get
Set(ByVal value As Decimal)
CType(MyBase.CellTemplate, NumericCell).MaxValue = value
End Set
End Property
''' <summary>
''' Get, set numeric control value
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property NumericControlValue() As Decimal
Get
Return CType(MyBase.CellTemplate, NumericCell).NumericControlValue
End Get
Set(ByVal value As Decimal)
CType(MyBase.CellTemplate, NumericCell).NumericControlValue = value
End Set
End Property
''' <summary>
''' Indicate number of decimal places to display
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property DecimalPlaces() As Integer
Get
Return CType(MyBase.CellTemplate, NumericCell).DecimalPlaces
End Get
Set(ByVal value As Integer)
CType(MyBase.CellTemplate, NumericCell).DecimalPlaces = value
End Set
End Property
''' <summary>
''' Detemine the value to increment or decrement each time button click
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Increment() As Integer
Get
Return CType(MyBase.CellTemplate, NumericCell).Increment
End Get
Set(ByVal value As Integer)
CType(MyBase.CellTemplate, NumericCell).Increment = value
End Set
End Property
Public Sub New()
MyBase.New(New NumericCell())
End Sub
Public Overrides Property CellTemplate() As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
' Ensure that the cell used for the template is a CalendarCell.
If (value IsNot Nothing) AndAlso _
Not value.GetType().IsAssignableFrom(GetType(NumericCell)) _
Then
Throw New InvalidCastException("Must be a Numeric Cell")
End If
MyBase.CellTemplate = value
End Set
End Property
''' <summary>
''' Override clone method to clone new added properties
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Overrides Function Clone() As Object
Dim obj As NumericColumn = MyBase.Clone()
obj.MaxValue = Me.MaxValue
obj.MinValue = Me.MinValue
obj.NumericControlValue = Me.NumericControlValue
obj.DecimalPlaces = Me.DecimalPlaces
obj.Increment = Me.Increment
Return obj
End Function
End Class
NumericCell class
Imports System
Imports System.Windows.Forms
Public Class NumericCell
Inherits DataGridViewTextBoxCell
''' <summary>
''' Min value for numeric control
''' </summary>
''' <remarks></remarks>
Private min As Decimal = 0.0
''' <summary>
''' Max value for numeric control
''' </summary>
''' <remarks></remarks>
Private max As Decimal = 100.0
''' <summary>
''' Value for numeric control
''' </summary>
''' <remarks></remarks>
Private controlValue As Decimal = 0.0
''' <summary>
''' Decimal places for numeric control
''' </summary>
''' <remarks></remarks>
Private places As Integer = 0
''' <summary>
''' Detemine the value to increment or decrement each time button click
''' </summary>
''' <remarks></remarks>
Private incrementStep As Integer = 1
''' <summary>
''' Get, set numeric control min value
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property MinValue() As Decimal
Get
Return Me.min
End Get
Set(ByVal value As Decimal)
Me.min = value
End Set
End Property
''' <summary>
''' Get, set numeric control max value
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property MaxValue() As Decimal
Get
Return Me.max
End Get
Set(ByVal value As Decimal)
Me.max = value
End Set
End Property
''' <summary>
''' Get, set numeric control value
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property NumericControlValue() As Decimal
Get
Return Me.controlValue
End Get
Set(ByVal value As Decimal)
Me.controlValue = value
End Set
End Property
''' <summary>
''' Indicate number of decimal places to display
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property DecimalPlaces() As Integer
Get
Return Me.places
End Get
Set(ByVal value As Integer)
Me.places = value
End Set
End Property
''' <summary>
''' Detemine the value to increment or decrement each time button click
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Increment() As Integer
Get
Return Me.incrementStep
End Get
Set(ByVal value As Integer)
Me.incrementStep = value
End Set
End Property
Public Sub New()
End Sub
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
ByVal initialFormattedValue As Object, _
ByVal dataGridViewCellStyle As DataGridViewCellStyle)
' Set the value of the editing control to the current cell value.
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, _
dataGridViewCellStyle)
Dim ctl As NumericEditingControl = CType(DataGridView.EditingControl, NumericEditingControl)
RemoveHandler ctl.Enter, AddressOf Me.OnNumericEnter
AddHandler ctl.Enter, AddressOf Me.OnNumericEnter
'config property for control
ctl.Minimum = Me.min
ctl.Maximum = Me.max
ctl.DecimalPlaces = Me.DecimalPlaces
ctl.Increment = Me.incrementStep
ctl.TextAlign = HorizontalAlignment.Right
ctl.ThousandsSeparator = True
' Use the default row value when Value property is null.
If (Me.Value Is Nothing) Then
ctl.Value = Me.controlValue
Else
ctl.Value = CType(Me.Value, Decimal)
End If
End Sub
''' <summary>
''' Handle on enter event of numeric
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub OnNumericEnter(ByVal sender As Object, ByVal e As EventArgs)
Dim control As NumericEditingControl = CType(sender, NumericEditingControl)
Dim strValue As String = control.Value.ToString("N2")
control.Select(0, strValue.Length)
End Sub
Public Overrides ReadOnly Property EditType() As Type
Get
' Return the type of the editing control that CalendarCell uses.
Return GetType(NumericEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType() As Type
Get
' Return the type of the value that CalendarCell contains.
Return GetType(String)
End Get
End Property
Public Overrides ReadOnly Property DefaultNewRowValue() As Object
Get
' Use the current date and time as the default value.
Return 0.0
End Get
End Property
''' <summary>
''' Override clone method to clone new added properties
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Overrides Function Clone() As Object
Dim obj As NumericCell = MyBase.Clone()
obj.MaxValue = Me.MaxValue
obj.MinValue = Me.MinValue
obj.NumericControlValue = Me.NumericControlValue
obj.DecimalPlaces = Me.DecimalPlaces
obj.Increment = Me.Increment
Return obj
End Function
End Class
NumericEditingControl class:
Imports System
Imports System.Windows.Forms
Public Class NumericEditingControl
Inherits NumericUpDown
Implements IDataGridViewEditingControl
Private dataGridViewControl As DataGridView
Private valueIsChanged As Boolean = False
Private rowIndexNum As Integer
Public Sub New()
'Me.Format = DateTimePickerFormat.Short
End Sub
Public Property EditingControlFormattedValue() As Object _
Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Value.ToString("N2")
End Get
Set(ByVal value As Object)
Try
' This will throw an exception of the string is
' null, empty, or not in the format of a date.
Me.Value = Decimal.Parse(value)
Catch
' In the case of an exception, just use the default
' value so we're not left with a null value.
Me.Value = 0.0
End Try
End Set
End Property
Public Function GetEditingControlFormattedValue(ByVal context _
As DataGridViewDataErrorContexts) As Object _
Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.Value.ToString("N2")
End Function
Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As _
DataGridViewCellStyle) _
Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
Me.Font = dataGridViewCellStyle.Font
Me.ForeColor = dataGridViewCellStyle.ForeColor
Me.BackColor = dataGridViewCellStyle.BackColor
End Sub
Public Property EditingControlRowIndex() As Integer _
Implements IDataGridViewEditingControl.EditingControlRowIndex
Get
Return rowIndexNum
End Get
Set(ByVal value As Integer)
rowIndexNum = value
End Set
End Property
Public Function EditingControlWantsInputKey(ByVal key As Keys, _
ByVal dataGridViewWantsInputKey As Boolean) As Boolean _
Implements IDataGridViewEditingControl.EditingControlWantsInputKey
' Let the DateTimePicker handle the keys listed.
'Select Case key And Keys.KeyCode
' Case Keys.Left, Keys.Up, Keys.Down, Keys.Right, _
' Keys.Home, Keys.End, Keys.PageDown, Keys.PageUp
' Return True
' Case Else
' Return Not dataGridViewWantsInputKey
'End Select
If key.KeyCode = Keys.Escape Then
End If
Return True
End Function
Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) _
Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
' No preparation needs to be done.
End Sub
Public ReadOnly Property RepositionEditingControlOnValueChange() _
As Boolean Implements _
IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property
Public Property EditingControlDataGridView() As DataGridView _
Implements IDataGridViewEditingControl.EditingControlDataGridView
Get
Return dataGridViewControl
End Get
Set(ByVal value As DataGridView)
dataGridViewControl = value
End Set
End Property
Public Property EditingControlValueChanged() As Boolean _
Implements IDataGridViewEditingControl.EditingControlValueChanged
Get
Return valueIsChanged
End Get
Set(ByVal value As Boolean)
valueIsChanged = value
End Set
End Property
Public ReadOnly Property EditingControlCursor() As Cursor _
Implements IDataGridViewEditingControl.EditingPanelCursor
Get
Return MyBase.Cursor
End Get
End Property
Protected Overrides Sub OnValueChanged(ByVal eventargs As EventArgs)
' Notify the DataGridView that the contents of the cell have changed.
valueIsChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnValueChanged(eventargs)
End Sub
End Class
The part responsible to deal with this behaviour is EditingControlWantsInputKey. By looking at the original code it is clear that this part has to be set by default to false (= returning to the previously stored value), but in your code it is set to true. The idea is setting this to true only for ("special") keys which shouldn't provoke the scaping of the value; that is, you don't need to mention here scape, just any other key (triggering this function) which you don't want to provoke the coming-back-to-previous-value behaviour.
Thus, solution:
Public Function EditingControlWantsInputKey(ByVal key As Keys, _
ByVal dataGridViewWantsInputKey As Boolean) As Boolean _
Implements IDataGridViewEditingControl.EditingControlWantsInputKey
Return False
End Function

VB.NET: Get dynamically value of constants

If have got the following definitions of constants:
Protected Const Xsl As String = "Configuration.Xsl"
Protected Const Form As String = "Settings.Form"
Protected Const Ascx As String = "Implementation.Ascx"
...
To fill a dictionary I use this constants as keys:
MyDictionary.Add(Converter.Xsl, "Item 1")
MyDictionary.Add(Converter.Form, "Item 2")
MyDictionary.Add(Converter.Ascx, "Item 3")
...
Now I run throug a loop of XML files and extract the name of the root node:
Dim document As New XmlDocument
document.Load(File.FullName)
Dim rootName As String = document.DocumentElement.Name
The root name matchs with the name of the constant. To get the value of an item from the dictionary I can use something like this:
Select Case rootName.ToUpper
Case "Xsl".ToUpper
DictionaryValue = MyDictionary(Class.Xsl)
Case "Form".ToUpper
DictionaryValue = MyDictionary(Class.Form)
Case "Ascx".ToUpper
DictionaryValue = MyDictionary(Class.Ascx)
...
Case Else
End Select
If a constant is added or removed I also have to change the selection. Is there another way to get the value of a constant? Something like
DictionaryValue = MyDictionary(SomeFunctionToGetConstantValue(rootName))
Thanks for any response.
Try this:
For Each sKey As String In MyDictionary.Keys
If rootName.Equals(sKey, StringComparison.CurrentCultureIgnoreCase) Then
DictionaryValue = MyDictionary(sKey)
Exit For
End If
Next
At least it will reduce the amount of coding in the select case.
#Clara Onager
My solution I used was the following
Me.GetType.GetField(
"Xsl",
Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static Or System.Reflection.BindingFlags.FlattenHierarchy
).GetValue(Nothing)
This is a bit of a whopper but I think it provides a pretty elegant solution overall. This is how it is used:
Public Class ConstantsExample
Public Sub UseConstant()
Dim value As String = Constants.Types(TypeA)
Dim category As String = Constants.Categories(General)
End Sub
End Class
As you can see the code where you use it is as short as it can be made. It does rely on a big pile of source code though:
Public Enum TypeCodes
<Description("Type A")> TypeA = 0
<Description("Type B")> TypeB
<Description("Type C")> TypeC
End Enum
Public Enum CategoryCodes
<Description("General")> General = 0
<Description("Specific")> Specific
<Description("Other")> Other
End Enum
Public NotInheritable Class Constants
#Region "Resources"
Private Shared myTypes As Dictionary(Of TypeCodes, ConstantItem) = Nothing
Public Shared ReadOnly Property Types() As Dictionary(Of TypeCodes, ConstantItem)
Get
If myTypes Is Nothing Then
myTypes = New Dictionary(Of TypeCodes, ConstantItem)
BuildTypes(myTypes)
End If
Return myTypes
End Get
End Property
Private Shared Sub BuildTypes(ByRef dict As Dictionary(Of TypeCodes, ConstantItem))
With dict
.Add(TypeCodes.TypeA, New ConstantItem(TypeCodes.TypeA.Description, "Type A are..."))
.Add(TypeCodes.TypeB, New ConstantItem(TypeCodes.TypeB.Description, "Type B are..."))
.Add(TypeCodes.TypeC, New ConstantItem(TypeCodes.TypeC.Description, "Type C are..."))
End With
End Sub
#End Region
#Region "Categories"
Private Shared myCategories As Dictionary(Of CategoryCodes, ConstantItem) = Nothing
Public Shared ReadOnly Property Categories() As Dictionary(Of CategoryCodes, ConstantItem)
Get
If myCategories Is Nothing Then
myCategories = New Dictionary(Of CategoryCodes, ConstantItem)
BuildCategories(myCategories)
End If
Return myCategories
End Get
End Property
Private Shared Sub BuildCategories(ByRef dict As Dictionary(Of CategoryCodes, ConstantItem))
With dict
.Add(CategoryCodes.General, New ConstantItem(CategoryCodes.General.Description, "General category"))
.Add(CategoryCodes.Specific, New ConstantItem(CategoryCodes.Specific.Description, "Specific category"))
.Add(CategoryCodes.Other, New ConstantItem(CategoryCodes.Other.Description, "Other category"))
End With
End Sub
#End Region
End Class
Public NotInheritable Class ConstantItem
#Region "Constructors"
''' <summary>
''' Default constructor.
''' </summary>
Public Sub New()
'Do nothing
End Sub
''' <summary>
''' Simple constructor.
''' </summary>
Sub New(value As String)
Me.Name = value
Me.Description = value
End Sub
''' <summary>
''' Proper constructor.
''' </summary>
Sub New(name As String, description As String)
Me.Name = name
Me.Description = description
End Sub
#End Region
Property Name As String
Property Description As String
''' <summary>
''' See http://stackoverflow.com/questions/293215/default-properties-in-vb-net
''' </summary>
Public Shared Widening Operator CType(value As String) As ConstantItem
Return New ConstantItem(value)
End Operator
''' <summary>
''' See http://stackoverflow.com/questions/293215/default-properties-in-vb-net
''' </summary>
Public Shared Widening Operator CType(value As ConstantItem) As String
Return value.Name
End Operator
End Class
Note the use of the Widening Operator to dispense with having to type .Item. If you'd rather not use the Widening Operator then simple comment that bit out and change Constants.Types(TypeA) to Constants.Types.Item(TypeA).
This is the Description Extension you may need:
Public Module Extensions
Private Enum SampleDescription
<Description("Item One")> ItemOne = 1
<Description("Item Two")> ItemTwo = 2
<Description("Item Three has a long description")> ItemThree = 3
End Enum
''' <summary>
''' This procedure gets the description attribute of an enum constant, if any. Otherwise it gets
''' the string name of the enum member.
''' </summary>
''' <param name="value"></param>
''' <returns></returns>
''' <remarks>Usage: myenum.Member.Description()
''' Add the Description attribute to each member of the enumeration.</remarks>
<Extension()> _
Public Function Description(ByVal value As [Enum]) As String
Dim fi As Reflection.FieldInfo = value.GetType().GetField(value.ToString())
Dim aattr() As DescriptionAttribute = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
If aattr.Length > 0 Then
Return aattr(0).Description
Else
Return value.ToString()
End If
End Function
End Module
And these are the Imports statements I used (the Assembly is called MyPatterns):
Imports System.ComponentModel
Imports MyPatterns.TypeCodes
Imports MyPatterns.CategoryCodes
Importing the two 'codes' allows you to do without the prefix for the Enum which shortens the code.