Add Computed Column to a DataTable

Hi Folks.
I'm trying out the new table-adapter gizmo's and attempting to extend a dataset by adding a new property in a partial class.
*************************************
Partial Public Class TipperRoundResults
Partial Public Class stp_GetViewTipsDataTable
Public ReadOnly Property SomeNewField() As String
Get
Return "Yipee!"
End Get
End Property
End Class
End Class
***************************************
This seems to work fine, and when I compile it and view it in the class viewer the property exists.
However I am having trouble binding to it in a GridView control via the ObjectDataSource. It doesn't appear in the list of 'Bound Columns' in the wizard, nor can I manually bind to it in a Template Field using:
<% #Bind("SomeNewField") %> which brings the error:
The error: DataBinding: 'System.Data.DataRowView' does not contain a property with the name 'SomeNewField'... So it obviously hasn't been added to the DataRowView.
I can however retrieve the value by doing this (which as I understand it, is pretty much exactly what the ObjectDataSource does):
***********************************************

Using da As New FTB.TipperRoundResultsTableAdapters.stp_GetViewTipsTableAdapte
Dim dt As FTB.TipperRoundResults.stp_GetViewTipsDataTable = da.GetRoundResultsByTipper(1, 23)
Response.Write(dt.SomeNewField.ToString)
End Using

**********************************************

So I'm wondering if anyone knows if:

a) there is a way to declare that property in the partial class that makes it 'bindable' - which I assume means adding it to the DataRowView somehow;

(b) there is a way to bind to the property in a template field using a different method other than 'bind'

Thanks in advance,
Andrew



Answer this question

Add Computed Column to a DataTable

  • Craig Cormier

    Thanks for that. Much appreciated.

    (PS - Why was this thread moved Got nothing to do with Windows Forms..)


  • Charles Darwin

    I have a similar problem like Andrew.


    I want to add a Computed Column to a DataTable. This column should be bindable, sortable, ... like any other column. I tried the following:

    • I use a typed DataSet (dsData) which is filled with ReadXml and written to the disk with WriteXml. The DataSet contains a Table (dtPerson) with the two Columns Firstname and Lastname. Now I want to Add the Computed Column FullName by extending the DataSet.
    • Extend the dsData-Class:

      Partial Class dsData
      Partial Class dtPerson

      Private FullNameColumn as DataColumn

      Public ReadOnly Property FullName() as DataColumn
      Get
      Return FullNameColumn
      End Get
      End Property

      Private Sub dtPersonDataTable_Initialized(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Initialized
      FullNameColumn = New System.Data.DataColumn("FullName", GetType(String), Nothing, System.Data.MappingType.Element)
      MyBase.Columns.Add(FullNameColumn)
      End Sub

      Private Sub dtPersonDataTable_ColumnChanged(ByVal sender As Object, ByVal e As System.Data.DataColumnChangeEventArgs) Handles Me.ColumnChanged
      Select Case e.Column.ColumnName
      Case Me.FirstNameColumn.ColumnName
      CType(e.Row, dtPersonRow).Item(FullNameColumn.ColumnName) = CType(e.Row, dtPersonRow).FirstName & " " & CType(e.Row, dtPersonRow).LastName
      Case Me.LastNameColumn.ColumnName
      CType(e.Row, dtPersonRow).Item(FullNameColumn.ColumnName) = CType(e.Row, dtPersonRow).FirstName & " " & CType(e.Row, dtPersonRow).LastName
      End Select
      End Sub

      End Class
      End Class

    This works quite good. I can bind this column to a DataGridView, but I have to bind it by code because it doesn't show up as a Column of the DataTable in the designer (DataSources).
    Another Problem is that the column is also written to the XML-File with WriteXml (and therefore the written data isn't consistent to the written Schema).
    So it works, but I'm not really happy with it.

    Does anyone know a better solution to create a computed Column
    (I think in this example I could achieve this by creating a Column with an expression. But I want a solution in which i can write code to compute the value).

    Robert


  • taral

    I've been facing similar problems - I guess I hoped that partial classes in .NET 2.0 would make customising strongly typed datasets a bit easier (maybe .NET 3.0, eh!). A way round this (I guess an answer to (b) above) is to add a handler for OnRowDataBound event of the gridview that you're binding to. So, for your example above:

    (1) Modify your extended typed dataset - you need to add the property to the relevant dataRow class rather than the data table. Something like:-

    Partial Public Class TipperRoundResults
    Partial Public Class stp_GetViewTipsDataRow
    Public ReadOnly Property SomeNewField() As String
    Get
    Return "Yipee!"
    End Get
    End Property
    End Class
    End Class

    (2) Replace the <asp:BoundField ../> column with an <asp:TemplateField../> like this:

    <asp:TemplateField HeaderText="Some New Field"><ItemTemplate><asp:Label ID="lblSomeNewField" runat="server" /></ItemTemplate></asp:TemplateField>

    (3) Add a link to the handler to your gridview:

    <asp:GridView ....

    OnRowDataBound="grdProperties_RowDataBound" />

    (4) Code the handler

    protected void grdProperties_RowDataBound(object sender, GridViewRowEventArgs e)
    {
    // Fired for each row being bound
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
    // Find the control in the template column for this row
    Label oLabel = (Label)e.Row.FindControl("lblSomeNewField");

    oLabel.Text = ((TipperRoundResults.stp_GetViewTipsDataRow) ((System.Data.DataRowView) e.Row.DataItem).Row).SomeNewField;
    }
    }

    hope this saves somebody some messing around!

    }


  • Add Computed Column to a DataTable