azamsharp
azamsharp

Reputation: 20086

Dictionary Binding to ListView WPF

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; 

Upvotes: 3

Views: 10759

Answers (3)

Ray Burns
Ray Burns

Reputation: 62919

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 ']').

Upvotes: 4

Jobi Joy
Jobi Joy

Reputation: 50038

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..

Upvotes: 0

Tony The Lion
Tony The Lion

Reputation: 63250

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>

Upvotes: 4

Related Questions