WPF中ListView的字典绑定

3
我有一个包含字典项的列表。这意味着:
List[0] = 字典项 => Item[0] = id,Item[1] = 名称,Item[2] = 数量。
我需要以网格方式在ListView控件中显示它。字典可能会有所不同。
更新:
列表中的每个项看起来像这样:
["_id"] = "11212131" ["Title"] = "这是标题" ["DateCreated"] = "某个日期"
字典内部的项可能不同。
更新2:
我正在使用以下代码创建动态GridView控件,然后将列添加到GridView控件中。它可以工作,但现在有一条长的水平线重复相同的列。我需要显示列名并在该列下显示属于该列的数据。
  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; 

更新3:

我已经接近成功。它可以工作,但只显示一个长的单行,其中包含重复的列。

 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; 

我确实理解这个想法,但你能否发布你的类,以便我们可以看到基础数据受到了什么限制? - Charlie
没有固定的类。对象被序列化,然后作为字典类型进行反序列化。 - azamsharp
3个回答

4
在您的ListView中创建一个ItemTemplate,如果您想要将Key/Value对都放入您的ListView中,可以采取以下方式:
<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>

以上代码仅显示第一个键,即“id”,以及“id”的值,即“22121231”。看起来我需要动态地完成这个。 - azamsharp

4

像这样生成您的GridView列:

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);
}

除非您的字典键包含特殊字符,否则这将起作用。使其工作的关键是绑定路径中的索引器语法('['和']')。


太棒了!我之前不知道这个关键语法。非常感谢 :) 它像魔法一样奏效了。 - azamsharp
我怎样在XAML中实现索引器? - azamsharp
在XAML中使用索引器语法只需在绑定路径中使用[],例如 Content="{Binding [KeyGoesHere]}",或者如果您想要索引一个属性,则使用 Content="{Binding DictionaryProperty[KeyGoesHere]}" - Ray Burns
如果键是动态的,则解决此问题的规范方法是使用MultiBinding和IMultiValueConverter。在MultiBinding中,第一个绑定找到要索引的对象,第二个绑定找到要使用的键。 IMultiValueConverter的主体类似于var dict = (Dictionary<K,V>)values[0]; var key = (K)values[1]; return dict[key]; - Ray Burns

0

你需要的是一个类似于ObservableCollection的ObservableDictionary,可以查看这个帖子获取一些提示http://social.msdn.microsoft.com/forums/en-US/wpf/thread/af80921b-8bf0-4763-bd30-1e01dfc6f132/

这里有你需要的答案 - http://drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/

我认为在代码后台创建UI元素并动态添加到VisualTree中并不是一个好主意。尝试使用纯数据绑定和ObservableDictionary,它会在内部创建你的GridView Datatemplates,并保持你的ListView在正确的列顺序中。

避免在循环中使用gridview.Columns.Add(gridViewColumn);。这显然会创建与行数相等的列。当然,我对你的DynamicDictionary Schema不是很清楚。


我不想使用ObservableDictionary,因为我没有观察或监视项目的意图。 - azamsharp
数据结构有点复杂。我有一个 List<Object> objs,每个对象都是一个包含 6-7 个键的字典。每个键都是列的名称。 - azamsharp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接