tags:

views:

281

answers:

3

I have a List which contains Dictionary items. This means

List[0] = Dictionary Item => Item[0] = id, Item[1] = Name, Item[2] = Amount.

I need to show this in a ListView control in a Grid manner. The dictionary can vary.

UPDATE:

Each Item in the List looks like this:

["_id"] = "11212131" ["Title"] = "this is title" ["DateCreated"] = "some date"

The items inside the dictionary can be different.

UPDATE 2:

I am using the following code to create a dynamic Gridview control and then add the columns into the GridView control. It works but now there is a long horizontal line of same repeative columns. I need to display the column name and under that the data that belongs to that column.

  var gridview = new GridView();

            foreach (var o in objs)
            {
                var dic = o as Dictionary<String, Object>;
                var enumerator = dic.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    var current = enumerator.Current;
                    var gridViewColumn = new GridViewColumn();
                    gridViewColumn.Header = current.Key; 
                    var binding = new Binding(current.Key);
                    //binding.Source = current;

                    gridViewColumn.DisplayMemberBinding = binding;

                    gridview.Columns.Add(gridViewColumn);

                }

                // new row 

            }

            lvCollections.View = gridview; 

UPDATE 3:

I am pretty close. It works but it displays only a long single row with repeated columns.

 var gridview = new GridView();


            foreach (var o in objs)
            {

                var dic = o as Dictionary<String, Object>;
                var enumerator = dic.GetEnumerator();
                while (enumerator.MoveNext())
                {var gridViewColumn = new GridViewColumn(); 
                    var current = enumerator.Current;
                    gridViewColumn.Header = current.Key;
                    var binding = new Binding();
                    binding.Source = current; 
                    binding.Path = new PropertyPath("Value"); 

                    gridViewColumn.DisplayMemberBinding = binding;
                    gridview.Columns.Add(gridViewColumn);

                }


                // new row 

            }

            lvCollections.ItemsSource = objs; 
            lvCollections.View = gridview; 
+1  A: 

Create a ItemTemplate in your ListView and if you want to place both Key/Value pairs inside your listview, you could do something like this:

<ListBox ItemsSource="{Binding Source={StaticResource YourDataObject}}">

 <ListBox.ItemTemplate>

  <DataTemplate>

   <StackPanel Orientation="Horizontal">

    <Label Content="{Binding Key}" />

    <TextBlock xml:space="preserve"></TextBlock>

    <Label Content="{Binding Value}" />

   </StackPanel>

  </DataTemplate>

 </ListBox.ItemTemplate>

</ListBox>
Tony
The above code only displays the first key which is "id" and the value of "id" which is "22121231". Seems like I need to do this dynamically.
azamsharp
A: 

What you need here is a ObservableDictionary works like ObservableCollection, Check out this thread to see some tips http://social.msdn.microsoft.com/forums/en-US/wpf/thread/af80921b-8bf0-4763-bd30-1e01dfc6f132/

Here is the answer for you - http://drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/

I think creating UIElements in the code behind and dynamically adding to the VisualTree is not at all a better idea. Try pure databinding with ObservableDictionary, which internally creates your GridView Datatemplates and will keep your ListView in proper column order.

Avoid gridview.Columns.Add(gridViewColumn); in the loop. It clearly creating Columns equal to the number of rows. Ofcourse I am not clear on your DynamicDictionary Schema..

Jobi Joy
Please see the updated post!
azamsharp
I don't want to use ObservableDictionary since I have no intentions in watching the items or observing them.
azamsharp
The data structure is little complicated. I have a List<Object> objs and then each object is a Dictionary which has 6-7 keys. Each key is the name of the column.
azamsharp
+2  A: 

Generate your GridView columns like this:

public void OnDataContextChanged(...)
{
  var distinctKeys = (
    from dict in (List<Dictionary<string,object>>)DataContext
    from key in dict.Keys
    select key
  ).Distinct();

  gridView.Columns.ReplaceWith(
    from key in distinctKeys
    orderby key
    select new GridViewColumn
    {
      Header = key,
      DisplayMemberBinding = new Binding("[" + key + "]"),
    });
}

// The above code uses an extension method like this
static void ReplaceWith<T>(this ObserableCollection<T> collection, IEnumerable<T> newItems)
{
  collection.Clear();
  foreach(var item in newItems)
    collection.Add(item);
}

This will work unless your dictionary key contains special characters. The key to making this work is the indxer sytax in the binding path (the '[' and ']').

Ray Burns
Awesome! I was not aware of the key syntax. Thanks a million :) That worked like a charm.
azamsharp
How can I do the indexer in XAML?
azamsharp
To use indexer syntax in XAML just use [] in the binding path, eg. `Content="{Binding [KeyGoesHere]}"`, or if you want to index a property, `Content="{Binding DictionaryProperty[KeyGoesHere]}"`
Ray Burns
What if the key is dynamic?
azamsharp
If the key is dynamic the canonical way to solve this is to use a MultiBinding and an IMultiValueConverter. Within the MultiBinding the first Binding finds the object to be indexed and the second Binding finds the key to use. The body of the IMultiValueConverter something like `var dict = (Dictionary<K,V>)values[0]; var key = (K)values[1]; return dict[key];`
Ray Burns