VB.NET add databinding to textbox control - vb.net

How do you create a databinding into a textbox that is created at runtime?
Code that created my textbox control
Private Function ADD_TEXTBOX_CONTROL(ByVal ParentControl As Control,
ByVal Name As String,
ByVal Text As String,
ByVal Width As Integer,
ByVal Pos_X As Integer,
ByVal Pos_Y As Integer,
ByVal oNewControlTooltip As String) As TextBox
Dim oTB As New TextBox
oTB.Name = Name
oTB.Text = Text
oTB.Width = Width
oTB.Location = New Drawing.Point(Pos_X, Pos_Y)
ParentControl.Controls.Add(oTB)
Return oTB
End Function
Lets say i would want to bind this textbox with a class property created in the namespace. So that if my textbox value changes, the Body_Cilinder.Height is adjusted as well.
Namespace BODY_NAMESPACE
' Class that defines all the Cilinders properties for easy access.
Class Body_Cilinder
' Counter to determinate the cilinder quantity required.
Public Shared Count As Integer = 0
' Property decalration fir cilinder properties
Private _Index As Integer
Private _Elevation As Double
Private _Height As Double
' Cilinder Index number As Integer for finding the position.
Public Property Index() As Integer
Get
Index = _Index
End Get
Set(ByVal value As Integer)
_Index = value
End Set
End Property
' Cilinder Elevation to define the cilinder elevation from the T.L.
Public Property Elevation() As Double
Get
Elevation = _Elevation
End Get
Set(value As Double)
_Elevation = value
End Set
End Property
' Cilinder Height to define the cilinder height.
Public Property Height() As Double
Get
Height = _Height
End Get
Set(value As Double)
_Height = value
End Set
End Property
' Add Cilinder count every-time a new "Body Cilinder" instance Is created
Public Sub New()
Count = Count + 1
End Sub
End Class
End Namespace
What do I need to add?
I found this example but I don't quite get how it functions
textBox1.DataBindings.Add _
(New Binding("Text", ds, "customers.custName"))
Link to source

Related

Create deep copy of object [duplicate]

This question already has answers here:
Deep cloning objects
(58 answers)
Closed 6 years ago.
I need help with the deep copying of objects in VB.net. I am aware of the fact that there is a great amount of topics dealing with that, but I was not able to adapt it to my problem. So hopefully someone can explain it to me using my code.
The problem: I have designed a class clsParameter which has one name, one unit, one value type and one value. The value can be a double or an object of type clsVectorParameter with the properties X,Y,Z. Now I want to do a deep copy of a parameter so that X,Y,Z are also copied.
Here are the two classes. The clone function below just represents a dummy. I know that it doesn't work like this but I didn't know a better way...
Public Class clsParameter
' Using the ICloneable interface
Implements ICloneable
' Variable definition
Private m_Name As String
Private m_Unit As String
Private m_Type As String
Private m_Value As Object
' Define set and get methods
Public Property Name As String
Get
Return m_Name
End Get
Set(ByVal value As String)
m_Name = value
End Set
End Property
Public Property Unit As String
Get
Return m_Unit
End Get
Set(ByVal value As String)
m_Unit = value
End Set
End Property
Public Property Value As Object
Get
Return m_Value
End Get
Set(ByVal value As Object)
m_Value = value
End Set
End Property
Public Property Type As String
Get
Return m_Type
End Get
Set(ByVal value As String)
m_Type = value
End Set
End Property
' Define constructor
Public Sub New(ByVal p_Name As String, ByVal p_Unit As String, ByVal p_Value As Object, ByVal p_Type As String)
m_Name = p_Name
m_Unit = p_Unit
m_Type = p_Type
m_Value = p_Value
End Sub
' Define Clone function to create independent copies of parameter instances
Public Function Clone() As Object Implements System.ICloneable.Clone
Dim cloneParam As New clsParameter(m_Name, m_Unit, m_Value, m_Type)
Return cloneParam
End Function
End Class
and the other class:
Public Class clsVectorParameter
Implements ICloneable
' Variable definition
Private m_x As Double
Private m_y As Double
Private m_z As Double
Public Property X As Double
Get
Return m_x
End Get
Set(ByVal value As Double)
m_x = value
End Set
End Property
Public Property Y As Double
Get
Return m_y
End Get
Set(ByVal value As Double)
m_y = value
End Set
End Property
Public Property Z As Double
Get
Return m_z
End Get
Set(ByVal value As Double)
m_z = value
End Set
End Property
' Define constructor
Public Sub New(ByVal p_x As Double, ByVal p_y As Double, ByVal p_z As Double)
m_x = p_x
m_y = p_y
m_z = p_z
End Sub
' Define Clone function to create independent copies
Public Function Clone() As Object Implements System.ICloneable.Clone
Dim cloneVecParam As New clsParameter(m_x, m_y, m_z, "Vec")
Return cloneVecParam
End Function
End Class
I use the class in this line:
Dim aNewParam As New clsParameter("Name", "Unit", New clsVectorParameter(x,y,z), "Type")
or
Dim aNewParam As New clsParameter("Name", "Unit", Double, "Type")
Later I need to create a deep copy of this aNewParam, so the x,y,z values are also independent for all parameters.
Thank you very much for your help!
Best regards,
Sebastian
Public Sub New(ByVal p_Name As String, ByVal p_Unit As String, ByVal p_Value As Object, ByVal p_Type As String)
m_Name = p_Name
m_Unit = p_Unit
m_Type = p_Type
If TypeOf (p_Value) Is Double Then
m_Value = p_Value
ElseIf TypeOf (p_Value) Is clsVectorParameter Then
m_Value = p_Value.Clone()
End If
End Sub
To keep your code in line with for example creating a clone of an XElement, do this from the constructor:
Dim obj1 = new clsVectorParameter(1, 1, 1)
Dim obj2 = new clsVectorParameter(obj1)
So now you only need to write an overloaded constructor, and there is no need for interfaces or seperate functions.
An overloaded constructor can be made like this: (you need to adapt this to your own class):
Public Class Foo
Dim x As Integer
Dim y As Integer
Dim z As Integer
Sub New(a As Integer, b As Integer, c As Integer)
x = a
y = b
z = c
End Sub
Sub New(old As Foo)
x = old.x
y = old.y
z = old.z
End Sub
End Class

Call Base functions from Child in VB.net

How to call the base functions in vb.net?
Imports System.Data.Sql
Imports System.Data.SqlClient
Public Class Box
Public length As Double ' Length of a box
Public breadth As Double ' Breadth of a box
Public height As Double ' Height of a box
Public function setLength(ByVal len As Double)
length = len
End Sub
Public Sub setBreadth(ByVal bre As Double)
breadth = bre
End Sub
Public Sub setHeight(ByVal hei As Double)
height = hei
End Sub
Public Function getVolume() As Double
Return length * breadth * height
End Function
End Class
It says syntax error when I use MyBase to call the base functions
Public Class myChild : Inherits Box
'box 1 specification
MyBase.setLength(6.0)
MyBase.setBreadth(7.0)
MyBase.setHeight(5.0)
'box 2 specification
MyBase.setLength(12.0)
MyBase.setBreadth(13.0)
MyBase.setHeight(10.0)
'volume of box 1
volume = MyBase.getVolume()
Console.WriteLine("Volume of Box1 : {0}", volume)
'volume of box 2
volume = MyBase.getVolume()
End Class
You can't call MyBase from there as the object hasn't yet been constructed.
A better implementation would be:
Box.vb
Public Class Box
Private mLength As Double ' Length of a box
Private mBreadth As Double ' Breadth of a box
Private mHeight As Double ' Height of a box
Public Sub New(ByVal length As Double, ByVal breadth As Double, ByVal height As Double)
Me.mLength = length
Me.mBreadth = breadth
Me.mHeight = height
End Sub
Public Property Length As Double
Get
Return Me.mLength
End Get
Set(ByVal value As Double)
Me.mLength = value
End Set
End Property
Public Property Breadth As Double
Get
Return Me.mBreadth
End Get
Set(ByVal value As Double)
Me.mBreadth = value
End Set
End Property
Public Property Height As Double
Get
Return Me.mHeight
End Get
Set(ByVal value As Double)
Me.mHeight = value
End Set
End Property
Public Function getVolume() As Double
Return Length * Breadth * Height
End Function
End Class
Child.vb
Public Class Child : Inherits Box
Public Sub New(ByVal length As Double, ByVal breadth As Double, ByVal height As Double)
MyBase.New(length, breadth, height)
End Sub
End Class
Example
Sub Main()
Dim box1 As New Child(6.0, 7.0, 5.0)
Dim box2 As New Child(12.0, 13.0, 10.0)
Console.WriteLine("box1 volume is: {0}", box1.getVolume())
Console.WriteLine("box2 volume is: {0}", box2.getVolume())
End Sub

Datagridview bound to object - Making the new rows appear blank

I have a Datagridview that changes its content according to a selection the user makes in a listBox.
The DGV consits of 2 comboboxes (Country, Product) and 1 textbox (Quantity).
I've created a class combined of 3 integers.
This class is used as a type of list, which is the datasource for the DGV.
There is also another list containing the prior list, so I have a list of datasources.
The DGV's datasource is a BindingSource that changes whenever the SelectedIndex of the listBox is fired.
My problem occurs whenever a new row is added to the DGV:
I use the BindingSource.AddNew which calls the constructor of the class, but it must assign values to each item in the class. That way, whenever I click any cell in the DGV I don't get a blank row.
Moreover, when the BS changes and then returned, another row is added.
What I want to get is a blank row - empty comboboxes and textbox.
Thanks for your help!
The class:
Public Class PoList
Private _CountryID As Integer
Private _ProductID As Integer
Private _Quantity As Integer
Public Sub New(ByVal CountryID As Integer, ByVal ProductID As Integer, ByVal Quantity As Integer)
_CountryID = CountryID
_ProductID = ProductID
_Quantity = Quantity
End Sub
Private Sub New()
_CountryID = 1
_ProductID = 2
_Quantity = Nothing
End Sub
Public Property CountryID() As Integer
Get
Return _CountryID
End Get
Set(ByVal value As Integer)
_CountryID = value
End Set
End Property
Public Property ProductID() As Integer
Get
Return _ProductID
End Get
Set(ByVal value As Integer)
_ProductID = value
End Set
End Property
Public Property Quantity() As Integer
Get
Return _Quantity
End Get
Set(ByVal value As Integer)
_Quantity = value
End Set
End Property
Public Shared Function CreateNewPoList() As PoList
Return New PoList
End Function
End Class
Private Sub List_AddRow(ByVal sender As Object, ByVal e As AddingNewEventArgs) Handles AllListBindingSource.AddingNew
e.NewObject = PoList.CreateNewPoList
End Sub
Creating a new inner list:
AllList.Add(New List(Of PoList))
AllListBindingSource.AddNew()
AllListBindingSource.DataSource = AllList(TableCounter)
AddPoDetails.DataSource = AllListBindingSource
SelectedIndexChanged event:
AllListBindingSource.DataSource = AllList(AddPoList.SelectedIndex)
AddPoDetails.DataSource = Nothing
AddPoDetails.DataSource = AllListBindingSource
Right, lets see if I can help you.
As I interpret it you have a list filled with lists. These lists don't know their own identity and is based on the current index in the list.
First of I wouldn't use Bindingsource.AddNew I would add the new object straight to the list instead.
AllList(TableCounter).Add(New Polist())
This way you know exactly how many objects has been created, by using events you aren't quite sure are you.
To refresh the list do this:
AllListBindingSource.ResetBindings(true)
Which will update your DGV with the new line.
Now you need to restructure your class since when you create a new Polist you set a value to nothing. This will crash your table. What you need to do is this:
Private _Quantity As String
Public Property Quantity() As String
Get
Return _Quantity
End Get
Set(ByVal value As String)
_Quantity = value
End Set
End Property
Using a string is the only way for you to get a blank textbox, I would recommend you to have 0 as default if you are using Quantity as an integer (which you should). Your constructor needs to be changed to this:
Private Sub New()
_CountryID = 0
_ProductID = 0
_Quantity = ""
End Sub
In your combobox columns you have to add a blank item in the top (I'm guessing your adding them manually), should be possible by having a blank row in the top of the items.

Adding a margin to custom datagridview column

I've used the following code, taken from here, to create my own custom column for datagridview, so that I can now have images and text in the same cell:
Public Class TextAndImageColumn
Inherits DataGridViewTextBoxColumn
Private imageValue As Image
Private m_imageSize As Size
Public Sub New()
Me.CellTemplate = New TextAndImageCell
End Sub
Public Overloads Overrides Function Clone() As Object
Dim c As TextAndImageColumn = TryCast(MyBase.Clone, TextAndImageColumn)
c.imageValue = Me.imageValue
c.m_imageSize = Me.m_imageSize
Return c
End Function
Public Property Image() As Image
Get
Return Me.imageValue
End Get
Set(ByVal value As Image)
Me.imageValue = value
Me.m_imageSize = value.Size
Dim inheritedPadding As Padding = Me.DefaultCellStyle.Padding
Me.DefaultCellStyle.Padding = New Padding(ImageSize.Width, inheritedPadding.Top, inheritedPadding.Right, inheritedPadding.Bottom)
End Set
End Property
Private ReadOnly Property TextAndImageCellTemplate() As TextAndImageCell
Get
Return TryCast(Me.CellTemplate, TextAndImageCell)
End Get
End Property
Friend ReadOnly Property ImageSize() As Size
Get
Return m_imageSize
End Get
End Property
End Class
Public Class TextAndImageCell
Inherits DataGridViewTextBoxCell
Private imageValue As Image
Private imageSize As Size
Public Overloads Overrides Function Clone() As Object
Dim c As TextAndImageCell = TryCast(MyBase.Clone, TextAndImageCell)
c.imageValue = Me.imageValue
c.imageSize = Me.imageSize
Return c
End Function
Public Property Image() As Image
Get
If Me.OwningColumn Is Nothing OrElse Me.OwningTextAndImageColumn Is Nothing Then
Return imageValue
Else
If Not (Me.imageValue Is Nothing) Then
Return Me.imageValue
Else
Return Me.OwningTextAndImageColumn.Image
End If
End If
End Get
Set(ByVal value As Image)
Me.imageValue = value
Me.imageSize = value.Size
Dim inheritedPadding As Padding = Me.InheritedStyle.Padding
Me.Style.Padding = New Padding(imageSize.Width, inheritedPadding.Top, inheritedPadding.Right, inheritedPadding.Bottom)
End Set
End Property
Protected Overloads Overrides Sub Paint(graphics As Graphics, clipBounds As Rectangle, cellBounds As Rectangle,
rowIndex As Integer, cellState As DataGridViewElementStates, value As Object, formattedValue As Object,
errorText As String, cellStyle As DataGridViewCellStyle, advancedBorderStyle As DataGridViewAdvancedBorderStyle,
paintParts As DataGridViewPaintParts)
MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
If Not (Me.Image Is Nothing) Then
Dim container As System.Drawing.Drawing2D.GraphicsContainer = graphics.BeginContainer
graphics.SetClip(cellBounds)
graphics.DrawImageUnscaled(Me.Image, cellBounds.Location)
graphics.EndContainer(container)
End If
End Sub
Private ReadOnly Property OwningTextAndImageColumn() As TextAndImageColumn
Get
Return TryCast(Me.OwningColumn, TextAndImageColumn)
End Get
End Property
End Class
It works very well, except that the image that I use is right at the edges of the cell. I'd like to give it a small margin. How can I do this?
You could add a property to TextAndImageCell like :
Private m_imagePadding As New Padding(3)
Public Property ImagePadding() As Padding
Get
Return m_imagePadding
End Get
Set(ByVal value As Padding)
m_imagePadding = value
End Set
End Property
and implement (in Paint) like :
graphics.DrawImageUnscaled(Me.Image, _
New Point(cellBounds.Location.X + m_imagePadding.Left, _
cellBounds.Location.Y + m_imagePadding.Top))
also would need to change in TextAndImageColumn :
Me.DefaultCellStyle.Padding = New Padding(ImageSize.Width + _
TextAndImageCellTemplate.ImagePadding.Right, inheritedPadding.Top, _
inheritedPadding.Right, inheritedPadding.Bottom)
There's room for refinement, obviously (trigger redraws on padding change, sort out row heights, text padding, etc) but something like this should work.

How can I extend a DataGridView ComboBox column's edit control by a second tiny button?

I insert DataGridViewComboBoxColumn columns in a DataViewGrid. That works fine.
Now, I want the user to be able to not only select one list item, but to "drilldown" into the list that is behind the combobox, allowing him to edit (insert/delete/update) the list.
I think it would be a good idea to display a ".." button right behind the dropdown button of the combobox. Pushing it leads to a dialog where the list can be maintained.
What I am stumbling upon is:
How would I create such a custom combobox? Is ComboBox (which is the base for the combo box that the combo box column creates as its edit control) open enough to accommodate such an additional button? What would be the container of the tiny buttoon -- the ComboBox descendant?
How I would make the grid create and handle such a custom combobox?
I currently try to solve this by subclassing DataGridViewComboBoxColum, using a DataGridViewComboBoxCell descendent in its CellTemplate assignment, and overriding PositionWEditingPanel and PositionEditingControl to manipulate the sizes of the panel and the combobox so I'd have space for the tiny button.
Is that the correct way?
Or would I have to create a DataGridViewColumn descendant which creates a Panel containing a DataGridView combobox edit control and the tiny button? How would I make sure the column keeps care of the combo box so it has the correct items etc?
Maybe I sound confused, but I probably am after weeks of VB code (doh)....
Here's the code I came up with. Only thing that's missing is the button press event handler.
Improvements welcome!
#Region "Custom column, cell and edit control for Combobox-with-a-'..'-Button"
Public Class DataGridViewComboBoxExColumn
Inherits DataGridViewComboBoxColumn
Public Sub New()
MyBase.New()
CellTemplate = New DataGridViewComboBoxExCell()
End Sub
Public Overrides Property CellTemplate As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
If (value IsNot Nothing) AndAlso Not value.GetType().IsAssignableFrom(GetType(DataGridViewComboBoxExCell)) Then
Throw New InvalidCastException("Must be a DataGridViewComboBoxExCell")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
Public Class DataGridViewComboBoxExCell
Inherits DataGridViewComboBoxCell
Dim HostingPanel As Panel
Public Sub New()
MyBase.New()
Dim TheButton As Button
HostingPanel = New Panel
HostingPanel.BorderStyle = BorderStyle.Fixed3D
HostingPanel.Padding = New Padding(0, 0, 0, 0)
HostingPanel.BackColor = Color.FromKnownColor(KnownColor.Control)
'HostingPanel.ForeColor = Color.Red ' Color.FromKnownColor(KnownColor.ButtonFace)
TheButton = New Button
TheButton.Text = ""
TheButton.BackColor = Color.FromKnownColor(KnownColor.ButtonFace)
TheButton.ImageList = DaCorFredProtMainForm.MainImageList
TheButton.ImageKey = "table_edit.png"
TheButton.Dock = DockStyle.Fill
HostingPanel.Controls.Add(TheButton)
End Sub
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As DataGridViewCellStyle)
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
If Not Me.DataGridView.EditingPanel.Controls.Contains(HostingPanel) Then ' Should always be true
Me.DataGridView.EditingPanel.Controls.Add(HostingPanel)
End If
End Sub
Public Overrides Sub DetachEditingControl()
If Me.DataGridView.EditingPanel.Controls.Contains(HostingPanel) Then ' Should always be true
Me.DataGridView.EditingPanel.Controls.Remove(HostingPanel)
End If
MyBase.DetachEditingControl()
End Sub
Public Overrides ReadOnly Property EditType As Type
Get
Return MyBase.EditType
End Get
End Property
Public Overrides ReadOnly Property ValueType As Type
Get
Return MyBase.ValueType
End Get
End Property
Public Overrides Function PositionEditingPanel(ByVal cellBounds As System.Drawing.Rectangle, ByVal cellClip As System.Drawing.Rectangle, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal singleVerticalBorderAdded As Boolean, ByVal singleHorizontalBorderAdded As Boolean, ByVal isFirstDisplayedColumn As Boolean, ByVal isFirstDisplayedRow As Boolean) As System.Drawing.Rectangle
cellBounds.Width += cellBounds.Height
cellClip.Width += cellClip.Height
Return MyBase.PositionEditingPanel(cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow)
End Function
Public Overrides Sub PositionEditingControl(ByVal setLocation As Boolean, ByVal setSize As Boolean, ByVal cellBounds As System.Drawing.Rectangle, ByVal cellClip As System.Drawing.Rectangle, ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal singleVerticalBorderAdded As Boolean, ByVal singleHorizontalBorderAdded As Boolean, ByVal isFirstDisplayedColumn As Boolean, ByVal isFirstDisplayedRow As Boolean)
MyBase.PositionEditingControl(setLocation, setSize, cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow)
Me.DataGridView.EditingControl.Width -= Me.DataGridView.EditingPanel.Height
HostingPanel.Width = Me.DataGridView.EditingPanel.Height
HostingPanel.Height = Me.DataGridView.EditingPanel.Height
HostingPanel.Location = New Point(DataGridView.EditingPanel.Size.Width - DataGridView.EditingPanel.Size.Height, 0)
End Sub
End Class
#End Region