Bind Dictionary to GridView
asp.net, data-binding, dictionary, gridview, vb.net
Solution
Here is a Gridview
<asp:GridView ID="GV" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="Key" HeaderText="Dictionary Key" />
<asp:BoundField DataField="Value" HeaderText="Dictionary Value" />
</Columns>
</asp:GridView>
Here is code to bind a dictionary to that Gridview
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim D As New Dictionary(Of Integer, String)
D.Add(1, "One")
D.Add(2, "Two")
D.Add(3, "Three")
GV.DataSource = D
GV.DataBind()
End Sub
Here is the output
What if my Value of of some type "MyClass?"
The Gridview will execute the `ToString` function of `MyClass`, per "Value" cell.
In your example, Override the `ToString` function on this class
Public Class TimeRangeCounter
Property ExactRangeMatch as Integer
Property SubRangeMatch as Integer
End Class
This is necessary because your "Value" is of time `TimeRangeCounter`
Summary
The Author's code had two problems.
- Problem 1 was generating an actual error and was solved by following my code example
- Problem 2 was the lack of a ToString function for the custom class used in the "Value" column of the Gridview
Problem
Referring to this thread: Algorithm to count the time that occured on the same period, how to bind the dictionary to the GridView? Pls take a look to the answer. I tried to add a GridView and then on the code-behind: `GV.DataSource = timeRangeCounts` and bind it, but in return: `The data source for GridView with id 'GV' did not have any properties or attributes from which to generate columns. Ensure that your data source has content.` How can I do that? Please take a look at the code below: The first helper class is used to hold the counts of exact and sub range matches: ``` Public Class TimeRangeCounter Property ExactRangeMatch as Integer Property SubRangeMatch as Integer End Class ``` The second helper class is used to help the dictionary know how one key (of type `TimeRange`) differs from another: ``` Public Class TimeRangeEqualityComparer Implements IEqualityComparer(Of TimeRange) Public Overloads Function Equals(left As TimeRange, right As TimeRange) _ As Boolean Implements IEqualityComparer(Of TimeRange).Equals Return left.ToString = right.ToString End Function Public Overloads Function GetHashCode(range As TimeRange) _ As Integer Implements IEqualityComparer(Of TimeRange).GetHashCode return range.ToString().GetHashCode() End Function End Class ``` The Third helper class stores the start and end times of a range: ``` Public Class TimeRange Private readonly _start Private readonly _end Public Readonly Property Start Get return _start End Get End Property Public Readonly Property [End] Get return _end End Get End Property Public Sub New(start As String, [end] As string) Me._start = start Me._end = [end] End Sub Public Overrides Function ToString() as String Return String.Format("{0}-{1}", Start, [End]) End Function End Class ``` So using the above we should be able to write this algorithm: ``` Dim columnLength As Integer = 5 Dim timeStart() As String = {"08.00", "08.00", "10.00", "08.00", "08.00"} Dim timeEnd() As String = {"08.50", "11.50", "11.00", "09.00", "08.50"} Dim comparer As New TimeRangeEqualityComparer() Dim timeRangeCounts As New Dictionary(Of TimeRange, TimeRangeCounter)(comparer) 'Count exact range matches while building dictionary For i = 0 to columnLength - 1 Dim key As TimeRange = New TimeRange(timeStart(i), timeEnd(i)) If timeRangeCounts.ContainsKey(key) timeRangeCounts(key).ExactRangeMatch += 1 Else Dim counter = New TimeRangeCounter() counter.ExactRangeMatch = 1 timeRangeCounts(key) = counter End If Next 'Count sub ranges For Each kvp in timeRangeCounts For Each key in timeRangeCounts.Keys If kvp.key.Start >= key.Start AndAlso _ kvp.Key.End <= key.End AndAlso _ kvp.key.ToString <> key.ToString then kvp.Value.SubRangeMatch += 1 End If Next Next 'Console.WriteLine(timeRangeCounts) GV.DataSource = timeRangeCounts GV.DataBind() ``` The gridview: ``` <asp:GridView ID="GV" runat="server"> <Columns> <asp:BoundField DataField="Key" HeaderText="Dictionary Key" /> <asp:BoundField DataField="Value" HeaderText="Dictionary Value" /> </Columns> </asp:GridView> ``` Then I tried to run it but the result is like: ``` Dictionary Key Dictionary Value 08:00:00-08:50:00 TimeRangeCounter 08:00:00-09:40:00 TimeRangeCounter 10:00:00-11:40:00 TimeRangeCounter ... ... ``` What's wrong with the code?