领带 GridView 用字典B. WPF C#

我正试图以编程方式将字典绑在一起 GridView 在 WPF/C#/. 字典的结构是这样的 -

字典 /string, Dictionary/string, int//

我可以将密钥键绑定到 GridView


Dictionary<string, dictionary<string,="" int="">&gt; result
GridView myGrid = new GridView//;
GridViewColumn gc = new GridViewColumn//;
gc.Header = "File Name";
gc.DisplayMemberBinding = new Binding/"Key"/;
myGrid.Columns.Add/gc/;


来源 gridview 出发

结果

我想在内部字典的键中创建一个标题集的列,并将其绑定到内部字典的值

有点
gc.DisplayMemberBinding = 新绑定 /"Value.Value"/;
这种词典的字典


{
'A', {/A1,1/,/A2,2/,/A3,3/}
'B', {/A1,4/,/A2,5/,/A3,6/}
'C', {/A1,7/,/A2,8/,/A3,9/}
}


因此, gridview 看起来像这样

--------------------------------------

姓名 | A1 | A2 | A3
--------------------------------------

a | 1 | 2 | 3

B | 4 | 5 | 6

C | 7 | 8 | 9
</string,>
已邀请:

帅驴

赞同来自:

嗯,映射嵌套词典 GridView... 它可以花一些时间和相当大的文字,所以你可以酿造新鲜的热咖啡。 - 准备好? 好的,让我们开始。

A
http://msdn.microsoft.com/en-u ... .aspx
- 它基本上只是控制的观看模式 ListView. 控制 ListView 可视化集合 /或名单/ 对象/价值 /无论他们是什么/.
如何与将显示的词典有关,将在一分钟内字面上解释。

如上所述,显示的数据存储在投资的字典中。 具体类型的裁航词典表示如下:


Dictionary< string, Dictionary<string, int=""> &gt;


钥匙 /外部的/ 字典是文件的名称,必须在列中显示 "FileName" 药品 GridView.
/内部的/ 与每个文件名关联的字典将包含第二个和后续列的值。

如上所述,字典是接口的实际实现。


ICollection&lt; KeyValuePair&lt; string, Dictionary<string, int=""> &gt; &gt;


事实上,这正是控制所需的内容。 ListView - 一组元素。 此集合中的每个元素都指的是此类型:


KeyValuePair&lt; string, Dictionary<string, int=""> &gt;


钥匙

在 KeyValuePair - 这是文件的名称。

价值

KeyValuePair - 这是 /内部的/ 词汇配对键 / 第二列和后续列的值。
这意味着这些元素中的每一个 KeyValuePair 包含一个全线的数据平滑。

现在最困难的事情开始了。 对于每列,必须访问相关数据 KeyValuePair.
不幸的是,它不适用于每个列的简单绑定。

然而, KeyValuePair 可以绑定到每列,以及特殊制造的帮助
http://msdn.microsoft.com/en-u ... .aspx
可以从中提取所需的信息 KeyValuePair.

在这里,我们必须做出决定。 我们可以相对简单,具有静态数的未分流列。
或者,如果目标是促进动态设置,添加或删除列,我们会投入更多的编码努力。
接下来将审查两种方法。

1. 简单,但静态和不灵活的方式。

进入K.

钥匙

KeyValuePair /文档名称/ 不需要值转换器。 相当简单的绑定

钥匙

财产。

访问存储的值 /内部的/ 字典 KeyValuePair, 将使用用户

IValueConverter

.
值转换器必须知道可恢复值的值。 这是作为公共财产实现的。

DictionaryKey

, 这允许您指定密钥 XAML.


[ValueConversion/typeof/KeyValuePair<string, dictionary<string,="" int="">&gt;/, typeof/string//]
public class GetInnerDictionaryValueConverter : IValueConverter
{
public string DictionaryKey { get; set; }

public object Convert/object value, Type targetType, object parameter, System.Globalization.CultureInfo culture/
{
if /!/value is KeyValuePair<string, dictionary<string,="" int="">&gt;//
throw new NotSupportedException//;

Dictionary<string, int=""> innerDict = //KeyValuePair<string, dictionary<string,="" int="">&gt;/ value/.Value;
int dictValue;
return /innerDict.TryGetValue/DictionaryKey, out dictValue// ? /object/ dictValue : string.Empty;
}

public object ConvertBack/object value, Type targetType, object parameter, System.Globalization.CultureInfo culture/
{
throw new NotImplementedException//;
}
}


然后 XAML 对于控制元素 ListView 可能看起来像这样。

假设显示列"FileName", "A1", "A2", "A3" /最后三是国内字典中的钥匙。/.
还要注意三种定制

实例 GetInnerDictionaryValueConverter, 它被创建为静态资源,并由相应的绑定使用。


<listview x:name="MyListGridView">
<listview.resources>
<my:getinnerdictionaryvalueconverter dictionarykey="A1" x:key="ConverterColum_A1"></my:getinnerdictionaryvalueconverter>
<my:getinnerdictionaryvalueconverter dictionarykey="A2" x:key="ConverterColum_A2"></my:getinnerdictionaryvalueconverter>
<my:getinnerdictionaryvalueconverter dictionarykey="A3" x:key="ConverterColum_A3"></my:getinnerdictionaryvalueconverter>
</listview.resources>
<listview.view>
<gridview allowscolumnreorder="true">
<gridviewcolumn displaymemberbinding="{Binding Key}" header="FileName"></gridviewcolumn>
<gridviewcolumn displaymemberbinding="{Binding Converter={StaticResource ConverterColum_A1}}" header="A1"></gridviewcolumn>
<gridviewcolumn displaymemberbinding="{Binding Converter={StaticResource ConverterColum_A2}}" header="A2"></gridviewcolumn>
<gridviewcolumn displaymemberbinding="{Binding Converter={StaticResource ConverterColum_A3}}" header="A3"></gridviewcolumn>
</gridview>
</listview.view>
</listview>


剩余待办事项的一切都是指定使用数据的实际词典

财产 ItemsSource 控制元素 ListView. 这可以通过 data binding 在 XAML 或在后面的代码中。

如上所述,这种方法非常简单易于实现。 缺点是列数是固定的,因为绑定到列所需的值转换器被声明为静态资源。
如果需要动态调整,则使用任意添加或删除列 DictionaryKeys, 我们需要摆脱这些静态转换器。 是什么导致我们的第二种方法......

2. 更复杂,但允许动态容易 setting/adding/removing 柱子

要解决动态设置,添加和删除具有任意的列 DictionaryKeys, 您可以使用自定义 GetInnerDictionaryValueConverter

,

早先介绍,但代码可能会令人困惑。
识别自定义类型的最佳方法 GridViewColumn, 这也可以实现任何必需的逻辑 IValueConverter 并照顾建立绑定。
单独的用户类型的值转换器,如前所述,不再需要,这将简化这些列的处理。

至于我们的示例,您只需要两个自定义列。 第一个用户列专为文件名而设计,看起来很简单:


public class GridViewColumnFileName : GridViewColumn
{
public GridViewColumnFileName//
{
DisplayMemberBinding = new Binding/"Key"/
{
Mode = BindingMode.OneWay
};
}
}


他所做的一切 - 这集合在代码中绑定。
你可以指出,我们也可以节省一个简单的 GridViewColumn 绑定 "{Binding Key}", 如前面的例子一样, - 你绝对是正确的。
我在这里展示了此实现,仅用于说明可能的方法。

表示来自内部词典值的列的用户类型有点复杂。
如前所述,此用户列应该知道显示值的键。
实施

界面 IValueConverter 作为此用户类型列的一部分,此类型的列可以自身使用作为绑定值的逆变器。


[ValueConversion/typeof/KeyValuePair<string, dictionary<string,="" int="">&gt;/, typeof/string//]
public class GridViewColumnInnerDictionaryValue : GridViewColumn, IValueConverter
{
public string InnerDictionaryKey
{
get { return _key; }
set
{
if /_key == value/ return;

_key = value;

if /string.IsNullOrWhiteSpace/value//
{
DisplayMemberBinding = null;
}
else if /DisplayMemberBinding == null/
{
DisplayMemberBinding = new Binding//
{
Mode = BindingMode.OneWay,
Converter = this
};
}
}
}

private string _key = null;

#region IValueConverter

public object Convert/object value, Type targetType, object parameter, System.Globalization.CultureInfo culture/
{
if /value is KeyValuePair<string, dictionary<string,="" int="">&gt;/
{
Dictionary<string, int=""> innerDict = //KeyValuePair<string, dictionary<string,="" int="">&gt;/ value/.Value;
int dictValue;
return /innerDict.TryGetValue/InnerDictionaryKey, out dictValue// ? /object/ dictValue : string.Empty;
}

throw new NotSupportedException//;
}

public object ConvertBack/object value, Type targetType, object parameter, System.Globalization.CultureInfo culture/
{
throw new NotImplementedException//;
}

#endregion IValueConverter
}


接口实现 IValueConverter 就像以前一样发生。
当然,

前任的

一种 GetInnerDictionaryValueConverter 它将被使用而不是将其逻辑作为一部分实现

GridViewColumnInnerDictionaryValue

,
但是,我想展示其他可能性。

创建一个控制要素 ListView 在 XAML 使用自定义列将如下所示:


<listview x:name="MyListGridView">
<listview.view>
<gridview allowscolumnreorder="true">
<my:gridviewcolumnfilename header="FileName"></my:gridviewcolumnfilename>
<my:gridviewcolumninnerdictionaryvalue header="A1" innerdictionarykey="A1"></my:gridviewcolumninnerdictionaryvalue>
<my:gridviewcolumninnerdictionaryvalue header="A2" innerdictionarykey="A2"></my:gridviewcolumninnerdictionaryvalue>
<my:gridviewcolumninnerdictionaryvalue header="A3" innerdictionarykey="A3"></my:gridviewcolumninnerdictionaryvalue>
</gridview>
</listview.view>
</listview>


而不是声明列 XAML 添加和删​​除列 / 的

特性 GridView.Columns 它也可以在代码中轻松执行。
再次,别忘了安装

财产 ListView ItemsSource 在字典或通过 data binding 在 XAML, 无论是在后面的代码中。
</string,></string,></string,></string,></string,></string,></string,></string,></string,></string,></string,>

冰洋

赞同来自:

如果您的列未修复,您不想硬编码它们 XAML, 另一个选项包数据 DataTable 并显示 DataGrid 使用自动列。


private static DataTable DictionaryToDataTable/
Dictionary<string, dictionary<string,="" int="">&gt; values,
string fixedColumn/
{

DataTable result = new DataTable//;
result.Columns.Add/fixedColumn/;

IEnumerable<string> headers = values.SelectMany/row =&gt; row.Value/
.Select/cell =&gt; cell.Key/.Distinct//;
headers.ForEach/b =&gt; result.Columns.Add/b//;

foreach /KeyValuePair<string, dictionary<string,="" int="">&gt; row in values/
{
DataRow dataRow = result.NewRow//;
dataRow[fixedColumn] = row.Key;
foreach /KeyValuePair<string, int=""> cell in row.Value/
{
dataRow[cell.Key] = cell.Value;
}

result.Rows.Add/row/;
}

return result;
}


然后 Xaml 相当简单:


<datagrid autogeneratecolumns="True" itemssource="{Binding MyDataTableProperty}"></datagrid>


</string,></string,></string></string,>

要回复问题请先登录注册