C# 在WPF C中用字典绑定GridView#
我试图以编程方式将字典绑定到WPF(C#)中的GridView中。字典的结构是-C# 在WPF C中用字典绑定GridView#,c#,wpf,visual-studio,gridview,dictionary,C#,Wpf,Visual Studio,Gridview,Dictionary,我试图以编程方式将字典绑定到WPF(C#)中的GridView中。字典的结构是- 字典(字符串,字典(字符串,int)) 我能够将主词典的键绑定到GridView Dictionary<string, Dictionary<string, int>> result GridView myGrid = new GridView(); GridViewColumn gc = new GridViewColumn(); gc.Header = "File Name";
字典(字符串,字典(字符串,int))
我能够将主词典的键绑定到GridView
Dictionary<string, Dictionary<string, int>> result
GridView myGrid = new GridView();
GridViewColumn gc = new GridViewColumn();
gc.Header = "File Name";
gc.DisplayMemberBinding = new Binding("Key");
myGrid.Columns.Add(gc);
所以gridview就像
--------------------------------------文件名| A1 | A2 | A3
--------------------------------------
A | 1 | 2 | 3
B|4|5|6
C | 7 | 8 | 9
好的,在GridView中显示嵌套字典。。。这可能需要一些时间和大量的文字,所以你可以自己煮一些新鲜的热咖啡。准备好的好的,让我们开始吧 A基本上只是ListView控件的视图模式。ListView控件可视化对象/值的集合(或列表)(无论这些对象可能是什么)。 这与将要显示的词典的关系将在一分钟内解释 如前所述,要显示的数据存储在嵌套字典中。具体的字典日期类型指定如下:
Dictionary< string, Dictionary<string, int > >
它所做的只是在代码隐藏中设置绑定。
您可能会指出,我们还可以像前面的示例中那样使用“{Binding Key}”绑定来保持简单的GridViewColumn,您是绝对正确的。
我在这里展示这个实现只是为了说明可能的方法
表示内部字典中的值的列的自定义列类型要复杂一些。
与之前的自定义值转换器一样,此自定义列需要知道要显示的值的键。
通过将IValueConverter接口作为此自定义列类型的一部分实现,此列类型可以将自身用作绑定的值转换器
[ValueConversion(typeof(KeyValuePair<string, Dictionary<string, int>>), 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>>)
{
Dictionary<string, int> innerDict = ((KeyValuePair<string, Dictionary<string, int>>) 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
}
[ValueConversion(typeof(KeyValuePair)、typeof(string))]
公共类GridViewColumnInnerDictionaryValue:GridViewColumn,IValueConverter
{
公共字符串InnerDictionaryKey
{
获取{return\u key;}
设置
{
if(_key==value)返回;
_键=值;
if(string.IsNullOrWhiteSpace(value))
{
DisplayMemberBinding=null;
}
else if(DisplayMemberBinding==null)
{
DisplayMemberBinding=新绑定()
{
Mode=BindingMode.OneWay,
转换器=此
};
}
}
}
私有字符串_key=null;
#区域变换器
公共对象转换(对象值、类型targetType、对象参数、System.Globalization.CultureInfo区域性)
{
如果(值为KeyValuePair)
{
字典innerDict=((KeyValuePair)值).value;
int值;
返回(innerDict.TryGetValue(InnerDictionaryKey,out-dictValue))?(对象)dictValue:string.Empty;
}
抛出新的NotSupportedException();
}
公共对象转换回(对象值、类型targetType、对象参数、System.Globalization.CultureInfo区域性)
{
抛出新的NotImplementedException();
}
#端区变换器
}
IValueConverter接口的实现与以前完全相同。
当然,可以使用以前的GetInnerDictionaryValueConverter类型,而不是将其逻辑实现为GridViewColumnInnerDictionaryValue的一部分,
但我想再次展示不同的可能性
使用自定义列类型在XAML中创建ListView控件如下所示:
<ListView x:Name="MyListGridView">
<ListView.View>
<GridView AllowsColumnReorder="true">
<My:GridViewColumnFileName Header="FileName" />
<My:GridViewColumnInnerDictionaryValue Header="A1" InnerDictionaryKey="A1" />
<My:GridViewColumnInnerDictionaryValue Header="A2" InnerDictionaryKey="A2" />
<My:GridViewColumnInnerDictionaryValue Header="A3" InnerDictionaryKey="A3" />
</GridView>
</ListView.View>
</ListView>
与在XAML中声明列不同,在GridView.columns属性中添加和删除列也可以在代码隐藏中轻松完成。
同样,不要忘记通过XAML或代码隐藏中的数据绑定将ListView的ItemsSource属性设置为字典。如果列不是固定的,并且不想在XAML中硬编码,另一个选项是将数据打包到DataTable中,并用自动列显示DataGrid
private static DataTable DictionaryToDataTable(
Dictionary<string, Dictionary<string, int>> values,
string fixedColumn)
{
DataTable result = new DataTable();
result.Columns.Add(fixedColumn);
IEnumerable<string> headers = values.SelectMany(row => row.Value)
.Select(cell => cell.Key).Distinct();
headers.ForEach(b => result.Columns.Add(b));
foreach (KeyValuePair<string, Dictionary<string, int>> 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;
}
专用静态数据表字典(
字典值,
字符串(固定列)
{
DataTable结果=新DataTable();
result.Columns.Add(fixedColumn);
IEnumerable headers=values.SelectMany(行=>row.Value)
.Select(cell=>cell.Key).Distinct();
headers.ForEach(b=>result.Columns.Add(b));
foreach(值中的KeyValuePair行)
{
DataRow DataRow=result.NewRow();
dataRow[fixedColumn]=行.键;
foreach(行中的KeyValuePair单元格。值)
{
dataRow[cell.Key]=cell.Value;
}
结果.行.添加(行);
}
返回结果;
}
那么Xaml非常简单:
<DataGrid ItemsSource="{Binding MyDataTableProperty}" AutoGenerateColumns="True" />
1。为什么,为什么你想用代码来做?XAML有什么问题?2.那么,你有什么问题?有例外吗?有什么抱怨吗?更具体地说……我只想将内部字典的值绑定到一列,但我无法做到这一点,因为在如何引用内部字典的值(结果[xyz].values().value)中,您能稍微简化一下您的问题吗?你想要什么还不清楚。是否要为字典中的每个键创建一列(字典存储在何处现在无关紧要)?那么每行的值是多少?很抱歉,我在问题中给出了字典结构,这是一个错误。我用DataGrid做了类似的事情。这并不是简单而直接的,因为您不能直接绑定到字典的值(您需要这个键)。它涉及数据单元的转换器,该转换器使用与特定列相关联的键,提取字典(th)的相应值
<ListView x:Name="MyListGridView">
<ListView.Resources>
<My:GetInnerDictionaryValueConverter x:Key="ConverterColum_A1" DictionaryKey="A1" />
<My:GetInnerDictionaryValueConverter x:Key="ConverterColum_A2" DictionaryKey="A2" />
<My:GetInnerDictionaryValueConverter x:Key="ConverterColum_A3" DictionaryKey="A3" />
</ListView.Resources>
<ListView.View>
<GridView AllowsColumnReorder="true">
<GridViewColumn Header="FileName" DisplayMemberBinding="{Binding Key}" />
<GridViewColumn Header="A1" DisplayMemberBinding="{Binding Converter={StaticResource ConverterColum_A1}}" />
<GridViewColumn Header="A2" DisplayMemberBinding="{Binding Converter={StaticResource ConverterColum_A2}}" />
<GridViewColumn Header="A3" DisplayMemberBinding="{Binding Converter={StaticResource ConverterColum_A3}}" />
</GridView>
</ListView.View>
</ListView>
public class GridViewColumnFileName : GridViewColumn
{
public GridViewColumnFileName()
{
DisplayMemberBinding = new Binding("Key")
{
Mode = BindingMode.OneWay
};
}
}
[ValueConversion(typeof(KeyValuePair<string, Dictionary<string, int>>), 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>>)
{
Dictionary<string, int> innerDict = ((KeyValuePair<string, Dictionary<string, int>>) 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
}
<ListView x:Name="MyListGridView">
<ListView.View>
<GridView AllowsColumnReorder="true">
<My:GridViewColumnFileName Header="FileName" />
<My:GridViewColumnInnerDictionaryValue Header="A1" InnerDictionaryKey="A1" />
<My:GridViewColumnInnerDictionaryValue Header="A2" InnerDictionaryKey="A2" />
<My:GridViewColumnInnerDictionaryValue Header="A3" InnerDictionaryKey="A3" />
</GridView>
</ListView.View>
</ListView>
private static DataTable DictionaryToDataTable(
Dictionary<string, Dictionary<string, int>> values,
string fixedColumn)
{
DataTable result = new DataTable();
result.Columns.Add(fixedColumn);
IEnumerable<string> headers = values.SelectMany(row => row.Value)
.Select(cell => cell.Key).Distinct();
headers.ForEach(b => result.Columns.Add(b));
foreach (KeyValuePair<string, Dictionary<string, int>> 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;
}
<DataGrid ItemsSource="{Binding MyDataTableProperty}" AutoGenerateColumns="True" />