Tuesday, 31 May 2016

DataBinding issues with a NULL or archived value

When binding web form controls to a data source you can often come unstuck when NULL values get returned from the database and you get dreaded run time NullReferenceExceptions. Although the examples below use Telerik controls, the equivalent ASP.NET controls can also be addressed in a similar manner

Binding a NULLable boolean field to a checkbox

When binding a boolean value to a grid, the add form will fail if it is NULLable due to there being no '3rd' option on a checkbox to handle the NULL value. To get around this we must set a default value manually when calling the InitInsert command as follows

Protected Sub rgd_ItemCommand(sender As Object, e As Telerik.Web.UI.GridCommandEventArgs) Handles rgd.ItemCommand
    If (e.CommandName = RadGrid.InitInsertCommandName) Then
        e.Canceled = True
        Dim newValues As System.Collections.Specialized.ListDictionary = New System.Collections.Specialized.ListDictionary()
        newValues("BoolField") = False
        e.Item.OwnerTableView.InsertItem(newValues)
    End If
End Sub

 

 
Binding a NULLable lookup table to Dropdown 

If you have a lookup table bound to a DropDownList/RadComboBox in a FormView/FormTemplate, by default it cannot handle NULL values if you create a line item for that NULL value. However by specifying a particular unused numeric value (such as 0 in this context will rarely by used for a table ID)

<telerik:RadComboBox ID="rcbForeignKeyID" runat="server" DataSourceID="sqlForeignKey" DataTextField="Name"
 DataValueField="ID" AppendDataBoundItems="true" SelectedValue='<%#Bind("ForeignKeyID")%>'>
    <Items>
        <telerik:RadComboBoxItem Text="No value..." Value="0" />
    </Items>
</telerik:RadComboBox>


On the Form's LinqDataSource we can then handle the Inserting & Updating events to set that 0 value to nothing which equates to DB NULL

Protected Sub lds_Inserting(sender As Object, e As System.Web.UI.WebControls.LinqDataSourceInsertEventArgs) Handles ldsForm.Inserting
    Dim rec As TableType = e.NewObject
    If rec IsNot Nothing Then
        If rec.ForeignKeyID = 0 Then rec.ForeignKeyID = Nothing
    End If
End Sub

Protected Sub lds_Updating(sender As Object, e As System.Web.UI.WebControls.LinqDataSourceUpdateEventArgs) Handles ldsForm.Updating
    Dim rec As TableType = e.NewObject
    If rec IsNot Nothing Then
        If rec.ForeignKeyID = 0 Then rec.ForeignKeyID = Nothing
    End If
End Sub




Binding a value no longer in the DataSource to a GridDropDownColumn

When using a dropdown in the edit form of a RadGrid you often encounter the scenario where the grid row value no longer exists in the dropdown data source due to the record being archived or some such. In order to work around this, we can manually add the existing record to the top of the dropdown so the SelectedValue binding won't break.

The aspx code should look something like this for the column specification
        <telerik:GridTemplateColumn UniqueName="ID" HeaderText="Header" AllowFiltering="false" DataType="System.Int32">
          <ItemTemplate>
            <asp:Label ID="lblHeader" runat="server" Text='<%#Eval("Name")%>' />
          </ItemTemplate>
          <EditItemTemplate>
            <telerik:RadComboBox ID="rcb" runat="server" Skin="Sunset" SelectedValue='<%#Bind("ID")%>'
                            OnDataBinding="rcb_DataBinding" AppendDataBoundItems="true"
              DataSourceID="sqlList" DataTextField="Name" DataValueField="ID" />
          </EditItemTemplate>
        </telerik:GridTemplateColumn>


The first bit of code required is an event handler for the RadComboBox / DropDownList control to add in the extra list item with the current value as follows
    'Add in option for existing record in dropdown
    Protected Sub rcb_DataBinding(sender As Object, e As EventArgs)
        Dim rcb As RadComboBox = DirectCast(sender, RadComboBox)
        Dim rci As New RadComboBoxItem("-- Existing Record --", rcb.SelectedValue)
        rcb.Items.Insert(0, rci)
    End Sub


The next bit of code is required to populate the text label of this new record with the actual value as follows
    'Set the label of the existing
    Protected Sub grd_ItemDataBound(ByVal sender As Object, ByVal e As Telerik.Web.UI.GridItemEventArgs) Handles grd.ItemDataBound
        If (TypeOf e.Item Is GridEditFormItem And e.Item.IsInEditMode) Then
            Dim editItem As GridEditFormItem = CType(e.Item, GridEditFormItem)
            Dim strName As String = editItem.ParentItem.DataItem("Name")
            Dim rcb As RadComboBox = DirectCast(e.Item.FindControl("rcb"), RadComboBox)
            If rcb IsNot Nothing Then rcb.Items(0).Text = strName
        End If
    End Sub


No comments:

Post a Comment