Reputation: 20086
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
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
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
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