Using a datagridview to add records - vb.net

I am using VS2008/.net fw 3.5sp1 and back into the coding life - and a little rusty to say the least :) Any help on the below would be great please.
I need to gather a list of input from a user, that I will work with later (pass to a teradata DWH with some other values). The input list involves two parts, a BSB ID and an Account ID. After some research it looks like the best option would be to create a class for the accounts, a list of accounts and bind that to a datagridview - of which I have done - but it looks like I can't add/edit. I have added a new button/add button to alter the data grid and get an error that I cannot programmatically add.
When I use accountList.AllowNew() = TRUE -- Error -- constructor on type bankaccount not found - but - I thought the constructor is the "new" sub in the class?
When I try accountsBindingSource.IsFixedSize = False it advises the property is read only.
For this - I've cut all the other code out to just this section, which requires one form (frmAccountLoad), with a datagridview dgvAccounts and a button btnNewLine.
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Data.Common
Imports System.Diagnostics
Imports System.Drawing
Imports System.Data.SqlClient
Imports System.Windows.Forms
'--------------------------------------------------------------------
Public Class frmAccountLoad
' This BindingSource binds the list to the DataGridView control.
Private accountsBindingSource As New BindingSource()
Private Sub frmAccountLoad_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Create list to hold accounts
Dim accountList As New BindingList(Of BankAccount)
accountList.AllowNew() = True
'accountList.AllowEdit = True
accountsBindingSource.DataSource = accountList
dgvAccounts.DataSource = accountsBindingSource
'dgvAccounts.Columns(0).HeaderText = "BSB"
'dgvAccounts.Columns(1).HeaderText = "Account"
End Sub
Private Sub btnNewLine_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNewLine.Click
'accountsBindingSource.IsFixedSize = False
accountsBindingSource.AddNew()
End Sub
End Class
'--------------------------------------------------------------------
Public Class BankAccount
'----------------------------------------------------------
'a bank account has both a BSB and an account number
Private m_BSB As String
Private m_Account As String
'----------------------------------------------------------
'Public Property
Public Property BSB() As String
Get
Return m_BSB
End Get
Set(ByVal value As String)
m_BSB = value
End Set
End Property
Public Property Account() As String
Get
Return m_Account
End Get
Set(ByVal value As String)
m_Account = value
End Set
End Property
'----------------------------------------------------------
Public Sub New(ByVal new_Bsb As String, ByVal new_Account As String)
m_BSB = new_Bsb
m_Account = new_Account
End Sub
End Class

To be able to call AddNew on your BindingList the BankAccount should have a parameter-less constructor.
You need to have a public parameter-less constructor if you need some initialization, or just remove any constructor if you don't need initialization, then the default parameter-less constructor will be used.
Public Class BankAccount
Public Property BSB As String
Public Property Account As String
Public Sub New()
'Do initialization here if you need
'Or Remove the constructor if you don't need any initialization.
End Sub
End Class
Also you don't need to set accountList.AllowNew = True. It's enough to use a BindingList(Of T) as DataSource.
Private accountList As BindingList(Of BankAccount)
Private Sub frmAccountLoad_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
accountList = New BindingList(Of BankAccount)
dgvAccounts.DataSource = BS
End Sub
Then you can call accountList.AddNew() wherever you need.

Related

PropertyChanged subroutine is not called/triggered

Windows Forms Application in VS2012
Target .NET Framework: 4.5
Created a project containing a Form (Form1) and a class (Class1). Form has a button (Button1) object. Code below:
Class1:
Imports System.ComponentModel
Public Class Class1
Implements INotifyPropertyChanged
Private _PropValue As String
Public Property PropValue As String
Get
Return _PropValue
End Get
Set(value As String)
_PropValue = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("PropValue"))
MsgBox("Event Raised") ' FOR TESTING
End Set
End Property
Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
End Class
Form1:
Imports System.ComponentModel
Public Class Form1
Private WithEvents _Class1 As Class1
Private Sub _Class1_PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Handles _Class1.PropertyChanged
MsgBox("Property Changed subroutine") ' FOR TESTING
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim tmpObj As Class1 = New Class1
tmpObj.PropValue = "Value-1"
tmpObj.PropValue = "Value-2"
End Sub
End Class
When executing the application and clicking on Button1, received 2 popup messages "Event Raised" from MsgBox in Class1. I'm trying to get the message "Property Changed subroutine" from _Class1_PropertyChanged subroutine. Haven't been successful so far.
You're not changing the property value of the object whose event you're handling. You're handling the event of the object you assign to the _Class1 field but you're changing the property value of a different object assigned to the tmpObj local variable. Get rid of that local variable and use the field only.

How to raise an events when global variable changed in vb.net

I've global variables in module level with below COM-interface types.
Imports System.IO
Imports simpackcomslvLib
Imports simpackcompostLib
Module Globals
Public Srv As SpckCOMApp
Public Mdl As IScrModel
Public Post As PostComApp
Public Res As PostComProject
End Module
In another classes some of my procedures change their object values. I'd like to run some of my procedures which made some changes on my tool's GUI when the for example Mdl value is changed.
I tried with below method which made for an integer type parameter but i didnt succeded for my case, i think because of their object(I types belongs to COM-interface.
Public Class myVar
Private mValue As Integer
Public Event VariableChanged(ByVal mvalue As Integer)
Public Property Variable() As Integer
Get
Variable = mValue
End Get
Set(ByVal value As Integer)
mValue = value
RaiseEvent VariableChanged(mValue)
End Set
End Property
End Class
Usage of above code in an example
Public Class Form1
Private WithEvents test As New myVar
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
test.Variable = CInt(TextBox1.Text)
End Sub
Private Sub VariableChanged(ByVal NewValue As Integer) Handles test.VariableChanged
MessageBox.Show(NewValue)
End Sub
End Class
Is there anyway to implement my below variables in a module such a way also using in module level is wrong should i move them under the class?
Module Globals
Public Srv As SpckCOMApp
Public Mdl As IScrModel
Public Post As PostComApp
Public Res As PostComProject
End Module

How value from different class/form can be changed without ByRef

Let's assume following example below:
When I call Form2 from Form1 and pass _name of Form1 value. When I show Form1's _name = Alex? I didn't change pname in Form2 and constructor doesn't contains ByRef.
Example code:
Public Form1
Public _name as String
Sub New
_name = "John"
Dim bla as New Form2(_name)
'now _name=Alex !!
End Sub
End Class
Public Form2
Property _name2 as String
Sub New(pname as String) 'no ByVal !!
_name2 = pname 'even if would be ByVal no pname changed !
_name2 = "Alex"
End Sub
End Class
Why is that happening?
Use Shared in variable _name:
Class Form1
Public Shared _name As String
Public Sub New()
_name = "John"
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Message "John"
MessageBox.Show(_name)
Dim bla As New Form2()
bla.Show()
' Message "Alex"
MessageBox.Show(_name)
End Sub
End Class
Public Class Form2
Property _name2 As String
Sub New()
_name2 = "Alex"
Form1._name = _name2
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' message Alex
MessageBox.Show(_name2)
' message Alex
MessageBox.Show(Form1._name)
End Sub
End Class
Or
When the modifier is not entered in the signature of a constructor (method), the default is byVal. If you want to change the value of the variable in form2 you must inform byref in the form2 constructor signature:
Sub New (byref _name as String)
To change the underlying value of an argument you must use the ByRef modifer:
Specifies that an argument is passed in such a way that the called procedure can change the value of a variable underlying the argument in the calling code.
This differs slightly from ByVal:
Specifies that an argument is passed in such a way that the called procedure or property cannot change the value of a variable underlying the argument in the calling code.
By not specifying a modifier in VB.NET the compiler by default will use ByVal.
It would be good to note here that although VB.NET uses ByVal by default if not specified, VBA does not and instead by default uses ByRef. Beware of this should you ever port code from one to the other.
Furthermore you are changing name2 when instead you should be changing pname if you want to change the underlying value.
Have a look at the following code based on your example:
Public Class Form1
Private _name As String
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
_name = "John"
Dim bla As New Form2(_name)
bla.Show()
Debug.WriteLine(_name)
End Sub
End Class
Public Class Form2
Private Property _name2 As String
Public Sub New(ByRef pname As String)
InitializeComponent()
_name2 = pname
pname = "Alex"
End Sub
End Class
Before passing the value to Form2 the name is "John":
At this point I am changing the value of pname to "Alex":
Note that although I have changed the value of pname To "Alex", _name2 is still set to "John".
Notice how the value of _name changes to "Alex" because of the change made to pname:
I'm not sure what it is you're trying to achieve here but hopefully this example gives you a better understanding. The alternative way would be to use a shared variable as explained in the other answer.

VB.NET Class with no constructor (no new instance can be declared)

I'm making my own message box class (called MessageBoxC, whatever), and like System.Windows.Forms.MessageBox, I want to make my class with no constructors and no possibility to declare a new instance of it.
E.g.:
Public Class MessageBoxC
Public Overloads Sub Show(ByVal message As String)
Me.Message = message
ProcessData() '(*)
Me.ShowDialog()
End Sub
End Class
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
System.Windows.Forms.MessageBox.Show("Hello World!") 'works fine
MessageBoxC.Show("Hello World!") 'works fine
Dim msgBox As New System.Windows.Forms.MessageBox 'and you'll get an error message here (**)
Dim msgBoxC As New MessageBoxC 'no error message
End Sub
End Class
(*) Not important. It just calculates text size (width and height in pixels) to correct form size if needed and the corresponding label gets value of Me.Message property.
(**) This one is what I mean. You cannot make a new instance of a MessageBox class, you'll get following error-message: "Type System.Windows.Forms.MessageBox has no constructors."
Well, my class has also no constructors, but it's possible to declare an instance of it. What's the trick here?
Thanks a lot!
Solved. Thanks to OneFineDay.
Public Class MessageBoxC
Private Sub New()
'Empty
End Sub
Public Overloads Shared Function Show(ByVal message As String) As System.Windows.Forms.DialogResult
Return Show(message, Constants.MyAppName, Constants.messageTitle, MessageBoxCButtons.OK, MessageBoxCIcon.Undefined)
End Function
Public Overloads Shared Function Show(ByVal message As String, _
ByVal caption As String, _
ByVal title As String, _
ByVal buttons As Library.MessageBoxCButtons, _
ByVal icon As Library.MessageBoxCIcon) As System.Windows.Forms.DialogResult
Dim msgBoxC As New CBox(message, caption, title, buttons, icon)
msgBoxC.ShowDialog()
Return msgBoxC.DialogResult
End Function
Private Class CBox
Inherits System.Windows.Forms.Form
Sub New(ByVal message As String, _
ByVal caption As String, _
ByVal title As String, _
ByVal buttons As Library.MessageBoxCButtons, _
ByVal icon As Library.MessageBoxCIcon)
MyBase.New()
InitializeComponent()
Me.Message = message
Me.Text = caption
Me.Title = title
Me.Buttons = buttons
Me.Icon64 = icon
Me.OptimizeMe()
End Sub
End Class
End Class
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim dialogResult As New DialogResult
dialogResult = MessageBoxC.Show("This is a simple message.")
MessageBox.Show(dialogResult.ToString)
End Sub
End Class
If you don't declare any constructors, a default constructor is automatically created (this is a public constructor with no parameters).
To prevent anyone creating an instance of your class, you can create a private constructor, like so:
Public Class MessageBoxC
Private Sub New()
' Prevents anyone creating an instance of this class.
End Sub
End Class
Note that your Show method will need to be declared Shared, otherwise you won't be able to call it. In fact, it would need to be Shared, even with the code you provided.
Here is one way to hide the constructor - mainly because the class in question is not accessible.
Public Class Form1
Private Sub meLoad() Handles Me.Load
'Usage
FooBar.Show("Hi")
End Sub
'...
End Class
Public Class FooBar
Private Sub New()
End Sub
Public Shared Sub Show(message As String)
Dim mbc As New MessageBoxC(message)
mbc.ShowDialog()
End Sub
'MessageBoxC is not exposed outside of Foobar which is the entry point
Private Class MessageBoxC : Inherits Form
'define cTor's as needed
Public Sub New(message As String)
Me.Text = message
End Sub
'define content
End Class
End Class

wordwrap does not work on datagridtextboxcolumn in VB.net

I have looked at previous answers on this blog which dont seem to help me.
I have a datagrid and add columns that are datagridtextboxcolumn . When I click on a cell on datagrid - if the line is too big for the width of cell , it will display on the following line, but when I am not clicked on the cell, the end of the line of text will not be displayed on the next line - and is therefore not displayed.
I derived a new class from datagridtextboxcolumn and attempted to override the paint and painttext methods and this appeared to have no effect - the text is still displayed in the column and only 1 line is displayed.
My code is
Here is the derived class: -
( below I have overridden the paint and painttext class in order to see which method has some effect on the display in the datagrid - but there is no effect occuring through this process of overriding.
enter code here
Imports Microsoft.VisualBasic
Imports System.ComponentModel
Imports System.Data
Imports System.Data.Common
Imports System.Data.OleDb
Imports System.Drawing
Imports System.Windows.Forms
Namespace DataGridRichTextBox
Public Class DataGridRichTextBoxColumn
Inherits DataGridTextBoxColumn
Private _source As CurrencyManager
Private _rowNum As Integer
Private _isEditing As Boolean
Public Sub New()
_source = Nothing
_isEditing = False
End Sub 'New
Protected Overloads Sub PaintText(ByRef g As Graphics, ByVal bounds As System.Drawing.Rectangle, ByRef Text As String, ByVal alligntoright As Boolean)
End Sub
Protected Overloads Sub PaintText(ByRef g As Graphics, ByVal bounds As System.Drawing.Rectangle, ByRef Text As String, ByRef s1 As System.Drawing.Brush, ByRef s2 As System.Drawing.Brush, ByVal alligntoright As Boolean)
End Sub
Protected Overloads Overrides Sub Paint(ByVal g As Graphics, ByVal bounds As System.Drawing.Rectangle, ByVal _source As CurrencyManager, ByVal num As Integer)
End Sub
Protected Overloads Overrides Sub SetColumnValueatrow(ByVal _source As CurrencyManager, ByVal num As Integer, ByVal obj As Object)
End Sub
End Class 'DataGridComboBoxColumn
End Namespace
'Here is where I add the derived class as an object to the datagrid : -
Imports System.Windows.Forms
Imports System.Data.SqlClient
Imports System.Drawing
Public Class DataGridMine
Inherits DataGrid
Public r_counter, column_num, x1 As Integer
Public x13 As Integer
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
Friend WithEvents SqlSelectCommand2 As New SqlCommand
Friend WithEvents DataSet51 As New tasks_trial2.DataSet5
Public WithEvents DataGridTableStyle1 As New DataGridTableStyle
Public WithEvents task_name_col, parent_col As New DataGridTextBoxColumn
Public WithEvents description_col As New DataGridRichTextBox.DataGridRichTextBoxColumn
Friend WithEvents SqlDataAdapter3 As New SqlDataAdapter
Friend WithEvents SqlDataAdapter2 As New SqlDataAdapter
Friend WithEvents SqlSelectCommand3 As New SqlCommand
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(Form1))
CType(Priority_code_table1, System.ComponentModel.ISupportInitialize).BeginInit()
SuspendLayout()
Me.DataMember = "tasks"
Me.DataSource = DataSet51
Me.Location = New Point(8, 230)
Me.Size = New Size(1117, 384)
Me.TabIndex = 0
Me.TableStyles.AddRange(New DataGridTableStyle() {DataGridTableStyle1})
SqlDataAdapter2.SelectCommand = SqlSelectCommand2
SqlDataAdapter2.TableMappings.AddRange(New System.Data.Common.DataTableMapping() {New System.Data.Common.DataTableMapping("Table", "tasks")})
SqlSelectCommand2.CommandText = ""
SqlSelectCommand2.Connection = SqlConnection10
DataGridTableStyle1.DataGrid = Me
DataGridTableStyle1.AllowSorting = False
column_num = 3
DataGridTableStyle1.HeaderForeColor = SystemColors.ControlText
DataGridTableStyle1.MappingName = "tasks"
DataGridTableStyle1.SelectionBackColor = Color.Aquamarine
DataGridTableStyle1.SelectionForeColor = Color.Black
DataGridTableStyle1.PreferredRowHeight = 10
DataGridTableStyle1.PreferredColumnWidth = 75
description_col.HeaderText = "Description"
description_col.MappingName = "description"
description_col.Width = 260
'.....................
' where column is description_col.
Public Sub add_columns(ByRef dgrid1 As DataGridMine, ByVal column As Object)
dgrid1.DataGridTableStyle1.GridColumnStyles.AddRange(New DataGridColumnStyle() {column})
End Sub
you don't have to do all that if you use a DataGridViewTextBoxColumn
just have to set some option via code or properties menu
go to your Columns listing and select the Column you want the text to be wrapped up and not cutt off.
go to DefaulCellStyle and set
WrapMode = True
additionally you could set this on the DGV Property Menu
AutoSizeColumnsMode to Fill
and
AutoSizeRowsMode to AllCells
that should do the Trick
this is all set in Properties Menu but you can do this in Code too so your choice