Tag Archives: VB.NET

Set DateTimePicker control value to Null

I achieve this by handling the Binding Source that the control is binding to and enabling the ShowCheckBox property.

The .NET DateTimePicker doesn’t accept blank or NULL value. I’ve seen many posts online that extend the controller to accept NULL value like this one or some other posts to change the formatting to custom and switching back again.

So if you don’t feel like adding a new custom control to your project just handle the underlying data source.

DateTimePicker with CheckBoxesSince I had many of the DateTimePicker controls, I made one function that handles the Leave event of each one like so:

    Private Sub DateTimePicker_Leave(sender As System.Object, e As System.EventArgs) Handles Inv_OriginalDateTimePicker.Leave
        'Handle the DateTimePicker so when it is unchecked it saves Null value
        Dim dt As DateTimePicker = sender

        If Not dt.Checked Then
            'Get the current record
            Dim row = DirectCast(Me.PO_JobsBindingSource.Current, DataRowView)

            row(dt.DataBindings.Item("Value").BindingMemberInfo.BindingField.ToString) = DBNull.Value

        End If
    End Sub
Share

Moving items between bound Listboxes

The other day I wanted to add news tags feature to a program, and to make it easy I wanted the user to be able of adding and removing news tags by double clicking a Listbox of available tags and assigned tags.

How I wanted Listboxes Tags to work

If you need to move items between bound Listboxes you cannot just use the Listbox.Add or Listbox.Remove methods. Instead you should add and remove rows to the Tables which they’re bound to.

This is the code I used:

    Private Sub AvailableTagListBox_DoubleClick(sender As System.Object, e As System.EventArgs) Handles AvailableTagListBox.DoubleClick
        If Not IsNothing(AvailableTagListBox.SelectedItem) Then
            'We are making a new row to be added to the table which then will appear in the listbox
            Dim Customer_News_Tags_Row As DataRow = MyDataSet.Customer_News_Tags.NewRow
            'Since I have a Parent and Child relation I'm taking the current parent ID
            Dim NewsRow = DirectCast(Me.Customer_NewsBindingSource.Current, DataRowView)
            'Parent ID
            Customer_News_Tags_Row("News_ID") = NewsRow("ID")
            'Fill the listbox item display field which I have it bound to
            Customer_News_Tags_Row("Tag") = AvailableTagListBox.Text

            'Adding new item to the other listbox by adding new row to its table
            MyDataSet.Customer_News_Tags.AddCustomer_News_TagsRow(Customer_News_Tags_Row)
            'Delete the listbox item by deleting the row in its table
            MyDataSet.News_Tags.Select("ID=" & AvailableTagListBox.SelectedValue)(0).Delete()

        End If

    End Sub

    Private Sub AssignedTagListBox_DoubleClick(sender As System.Object, e As System.EventArgs) Handles AssignedTagListBox.DoubleClick
        If Not IsNothing(AssignedTagListBox.SelectedItem) Then

            Dim News_Tags_Row As DataRow = MyDataSet.News_Tags.NewRow
            'I'm using a field called Tag
            News_Tags_Row("Tag") = AssignedTagListBox.Text

            MyDataSet.News_Tags.AddNews_TagsRow(News_Tags_Row)
            'Here I'm matching with a field I have called Tag to delete from Assigned listbox items
            MyDataSet.Customer_News_Tags.Select("Tag='" & AssignedTagListBox.SelectedValue & "'")(0).Delete()

        End If
    End Sub

Hope this helps, and if you need any clarifications let me know 🙂

Share

Editable bound DataGridView ComboBox

A bound DataGridView ComboBox Column doesn’t allow user input. You might come across a situation where you need to make it easier for the user to select an item from the ComboBox and at the same time allow them to just enter free text.

The trick is to make the ComboBox column without a DataSource and then you load the items by code. Also you have to handle a couple of stuff such as the EditingControlShowing event to convert the ComboBox style to be DropDown instead of DropDownList, and some other handling to commit the ComboBox change.

I will leave you with the code:

Private Sub MyForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

    'Get ComboBox items
    Me.ComboBoxTableAdapter.Fill(Me.MyDataSet.ComboBoxTable)

    'Fill the ComboBox
    Dim row As DataRow
    For Each row In Me.MyDataSet.ComboBoxTable
        'Generic list used as a trick to have the ComboBox Items added with Value
        MyComboBox.Items.Add(New GenericListItem(Of String)(row.Item("ColName"), row.Item("ColValue")))

    Next

    Me.GridTableAdapter.Fill(Me.MyDataSet.GridTable)

    'Adding Grid handler to detect change in run time
    AddHandler MyDataGridView.CurrentCellDirtyStateChanged, AddressOf MyDataGridView_CurrentCellDirtyStateChanged

End Sub

'Change ComboBox style to DropDown
  Private MyDataGridView_EditingControlShowing(ByVal sender As Object, ByVal e As MyDataGridViewEditingControlShowingEventArgs) Handles MyDataGridView.EditingControlShowing
        If TypeOf e.Control Is ComboBox Then
Dim cb As ComboBox = TryCast(e.Control, ComboBox)

            cb.DropDownStyle = ComboBoxStyle.DropDown
        End If

'When an item is selected from the ComboBox update the cell value
        If MyDataGridView.Columns(MyDataGridView.CurrentCell.ColumnIndex).Name = "MyComboBox" Then
Dim selectedComboBox As ComboBox = DirectCast(e.Control, ComboBox)
            RemoveHandler selectedComboBox.SelectionChangeCommitted, AddressOf selectedComboBox_SelectionChangeCommitted
            AddHandler selectedComboBox.SelectionChangeCommitted, AddressOf selectedComboBox_SelectionChangeCommitted

        End If

    End Sub

Private Sub selectedComboBox_SelectionChangeCommitted(ByVal sender As Object, ByVal e As EventArgs)
    Try

        Dim selectedCombobox As ComboBox = DirectCast(sender, ComboBox)
        If selectedCombobox.SelectedItem IsNot Nothing Then

            'Use the List we created earlier so we could retrieve the Value instead of the diplayed text
            Dim oItem As GenericListItem(Of String) = CType(selectedCombobox.SelectedItem, GenericListItem(Of String))

            Me.MyDataGridView.Item("ColumnName", MyDataGridView.CurrentCell.RowIndex).Value = oItem.Value()

        End If

    Catch ex As Exception
        MessageBox.Show(ex.Message)

    End Try
End Sub

Private Sub MyDataGridView_CurrentCellDirtyStateChanged(ByVal sender As Object, ByVal e As EventArgs) Handles MyDataGridView.CurrentCellDirtyStateChanged
    'Commit the change which was in run time so the Value changed event happens and then allow one check box
    If MyDataGridView.IsCurrentCellDirty Then
        MyDataGridView.CommitEdit(MyDataGridViewDataErrorContexts.Commit)
    End If
End Sub

Private Sub MyDataGridView_CellValidating(sender As Object, e As System.Windows.Forms.MyDataGridViewCellValidatingEventArgs) Handles MyDataGridView.CellValidating

    'Allow user to enter new values for all MyDataGridViewComboBox controls in the MyDataGridView
    If (TypeOf CType(sender, MyDataGridView).EditingControl Is MyDataGridViewComboBoxEditingControl) Then
        Dim cmb As MyDataGridViewComboBoxEditingControl = CType(CType(sender, MyDataGridView).EditingControl, MyDataGridViewComboBoxEditingControl)
        If Not cmb Is Nothing Then
            Dim grid As MyDataGridView = cmb.EditingControlMyDataGridView
            Dim value As Object = cmb.Text
            '// Add value to list if not there
            If cmb.Items.IndexOf(value) = -1 Then
                '// Must add to both the current combobox as well as the template, to avoid duplicate entries...
                cmb.Items.Add(value)
                Dim cmbCol As MyDataGridViewComboBoxColumn = CType(grid.Columns(grid.CurrentCell.ColumnIndex), MyDataGridViewComboBoxColumn)
                If Not cmbCol Is Nothing Then
                    cmbCol.Items.Add(value)
                End If
            End If
            grid.CurrentCell.Value = value
        End If
    End If

    ''Following Works for a specific combobox ///////////

    'If e.ColumnIndex = MyMyDataGridView.Columns("MyDataGridViewComboBoxColSize").Index Then 'CType(sender, MyDataGridView).CurrentCell.ColumnIndex

    ' 'Dim cmb As ComboBox = CType(e.Control, ComboBox)

    ' Dim cmb As MyDataGridViewComboBoxEditingControl = CType(CType(sender, MyDataGridView).EditingControl, MyDataGridViewComboBoxEditingControl)

    ' If Not cmb Is Nothing Then

    ' Dim grid As MyDataGridView = cmb.EditingControlMyDataGridView

    ' Dim value As Object = cmb.Text

    ' '// Add value to list if not there

    ' If cmb.Items.IndexOf(value) = -1 Then

    ' '// Must add to both the current combobox as well as the template, to avoid duplicate entries...

    ' cmb.Items.Add(value)

    ' Dim cmbCol As MyDataGridViewComboBoxColumn = CType(grid.Columns(grid.CurrentCell.ColumnIndex), MyDataGridViewComboBoxColumn)

    ' If Not cmbCol Is Nothing Then

    ' cmbCol.Items.Add(value)

    ' End If

    ' grid.CurrentCell.Value = value

    ' End If

    ' End If

    'End If
End Sub

Public Class GenericListItem(Of T)
    Private mText As String
    Private mValue As T

    Public Sub New(ByVal pText As String, ByVal pValue As T)
        mText = pText
        mValue = pValue
    End Sub

    Public ReadOnly Property Text() As String
        Get
            Return mText
        End Get
    End Property

    Public ReadOnly Property Value() As T
        Get
            Return mValue
        End Get
    End Property

    Public Overrides Function ToString() As String
        Return mText
    End Function
End Class

I hope this helps, and if you have any question let me know.

Happy coding 🙂

Share

Handle Date formats problems in .NET

Recently I faced a problem when I was deploying a project on a remote server.

Locally my ASP.Net web application was working like breeze, but when I deployed it on a remote server the problem appeared. When the user try to generate a report selecting a date range and hit go, the user gets an error message “String was not recognized as a valid DateTime”.

The report is consisted of two Calendars with “dd/MM/yyyy” date format, a Grid View and a Text box to filter the grid. I used the Visual Studio to create the GridView which takes the Select parameters from both Calendars when binding. The date column in the MS SQL Server 2005 is of DateTime format and it shows like “31/05/ 2009 11:10:00 AM”.

So obviously there is a misunderstanding of the date entered, which means a difference in the Culture environment. I tried changing the regional settings of the server to match local machines settings, but that didn’t work; still the same error. I also tried to force the Culture info in the web.config, but that also didn’t work for me!

Then I was only left with formatting the date manually to the server’s taste 🙂

To do that, I used the Selecting event of the SQL Data Source to modify the parameter data before going to the Database. Note that if your case is with updating or deleting, .Net also has those events for you to use.

So I used the following function to convert the date format of my Calendar which is “dd/MM/yyyy” to whatever the machine likes 🙂 (Is compatible with).

Public Shared Function ConvertToDate(ByVal dateString As String, ByRef result As DateTime) As Boolean
Try

‘Here is the date format you desire to use

Dim supportedFormats() As String = New String() {“dd/MM/yyyy”}

‘Now it will be converted to what the machine supports

result = DateTime.ParseExact(dateString, supportedFormats,System.Globalization.CultureInfo.CurrentCulture, System.Globalization.DateTimeStyles.None)

Return True
Catch ex As Exception
Return False
End Try
End Function

And from the Selecting event of the SQL Data Source:

Protected Sub SqlDataSource1_Selecting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceSelectingEventArgs) Handles SqlDataSource1.Selecting

Dim d1, d2 As Date

If txtFrom.Text <> “” And txtTo.Text <> “” Then

ConvertToDate(txtFrom.Text, d1)
ConvertToDate(txtTo.Text, d2)

e.Command.Parameters.Item(0).Value = d1

e.Command.Parameters.Item(1).Value = d2
End If
End Sub

I just wanted to share this, I hope this would help 😉

Share