41

I have a dictionary object <string, string> and would like to bind it to a repeater. However, I'm not sure what to put in the aspx markup to actually display the key-value pair. There are no errors thrown and I can get it to work with a List. How do I get a dictionary to display in a repeater?

George Stocker
  • 55,025
  • 29
  • 167
  • 231
XSL
  • 2,795
  • 7
  • 33
  • 58

4 Answers4

47

An IDictionary<TKey,TValue> is also an ICollection<KeyValuePair<TKey, TValue>>.

You need to bind to something like (untested):

((KeyValuePair<string,string>)Container.DataItem).Key
((KeyValuePair<string,string>)Container.DataItem).Value

Note that the order in which the items are returned is undefined. They may well be returned in the insertion order for small dictionaries, but this is not guaranteed. If you need a guaranteed order, SortedDictionary<TKey, TValue> sorts by key.

Or if you need a different sort order (e.g. by value), you could create a List<KeyValuePair<string,string>> of your key-value pairs, then sort it, and bind to the sorted list.

Answer: I used this code in the markup to display the key and value individually:

<%# DataBinder.Eval((System.Collections.Generic.KeyValuePair<string, string>)Container.DataItem,"Key") %>
<%# DataBinder.Eval((System.Collections.Generic.KeyValuePair<string, string>)Container.DataItem,"Value") %>
George Stocker
  • 55,025
  • 29
  • 167
  • 231
Joe
  • 114,633
  • 27
  • 187
  • 321
  • Is there a way to return the items in a certain order? In my (very short test) list of 4 items, they are returned in the order they've been placed. – XSL Feb 16 '10 at 17:44
32

<%# Eval("key")%> worked for me.

Liam
  • 22,818
  • 25
  • 93
  • 157
Arun Krish
  • 337
  • 3
  • 2
11

Bind to the values collection of the dictionary.

myRepeater.DataSource = myDictionary.Values
myRepeater.DataBind()
Jason Berkan
  • 8,335
  • 6
  • 27
  • 39
  • Thanks. I'd like to display the Keys and Values, so I just used `myDictionary`. In the markup, I used ``. This works, but it shows both, the key and value as one 'item'. Is there a way to get the `key` and `value` individually, so they can be formatted separately? – XSL Feb 16 '10 at 17:36
  • 2
    Yes. The objects in a dictionary are KeyValuePairs, so you can cast the DataItem as Joe shows in his answer. – Jason Berkan Feb 16 '10 at 17:59
2

Write a property in your code-behind of the type of an entry in your bound dictionary. So say, for example, I am binding a Dictionary<Person, int> to my Repeater. I would write (in C#) a property like this in my code-behind:

protected KeyValuePair<Person, int> Item
{
    get { return (KeyValuePair<Person, int>)this.GetDataItem(); }
}

Then, in my view I can use code segments like this:

<span><%# this.Item.Key.FirstName %></span>
<span><%# this.Item.Key.LastName %></span>
<span><%# this.Item.Value %></span>

This makes for much cleaner markup. And while I would prefer less generic names for the values being referenced, I do know that Item.Key is a Person and Item.Value is an int and they are strongly-typed as such.

You can (read: should), of course, rename Item to something more symbolic of an entry in your dictionary. That alone will help reduce any ambiguity in the naming in my example usage.

There is certainly nothing to prevent you from defining an additional property, say like this:

protected Person CurrentPerson
{
    get { return ((KeyValuePair<Person, int>)this.GetDataItem()).Key; }
}

And using it in your markup thusly:

<span><%# this.CurrentPerson.FirstName %></span>

...none of which prevents you from also accessing the corresponding dictionary entry's .Value.

JMD
  • 7,213
  • 3
  • 26
  • 38