WPF MVVM 将 Dictionary<String, List<String>> 绑定到数据网格
Posted
技术标签:
【中文标题】WPF MVVM 将 Dictionary<String, List<String>> 绑定到数据网格【英文标题】:WPF MVVM Bind Dictionary<String, List<String>> to datagrid 【发布时间】:2016-04-01 15:00:48 【问题描述】:我无法以正确的布局将我的Dictionary<string, List<string>>
绑定到我的 WPF 数据网格。
这是我的数据对象:
public class Result
public Result(string type, string name, Dictionary<string, List<string>> partners)
Type = type;
Name = name;
Partners = partners;
public string Type get; set;
public string Name get; set;
public Dictionary<string, List<string>> Partners get; set;
我填充了虚拟数据并作为我的视图模型的公共属性公开:
public class MainViewModel
public MainViewModel()
var partners = new Dictionary<string, List<string>>
"Company", new List<string> "company1", "company2",
"Operator", new List<string> "false", "true",
"Interest", new List<string> "40%", "60%",
"Type", new List<string> "type1", "type2"
;
Asset = new Result("TestType", "TestName", partners);
public Result Asset get; set;
我正在尝试将Partners
字典绑定到我的数据网格。每个字典条目(例如公司 / 运营商 / 兴趣 / 类型)的 Key
应该构成我的数据网格的标题,相应的值填充列。像这样:
Company | Operator | Interest | Type
company1 false 40% type1
company2 true 60% type2
我怎样才能做到这一点?我一直在查看this question,但数据与我想要的相反。我希望我的键作为数据网格列标题(我不介意对标题进行硬编码,因为我相信标题属性不能使用数据绑定)。到目前为止,这是我的 XAML,itemsource 已正确绑定,但我不知道如何以我需要的格式获取数据:
<DataGrid x:Name="dg" ItemsSource="Binding Asset.Partners" AutoGenerateColumns="false">
<DataGrid.Columns>
<DataGridTextColumn Header="Company" Binding="Binding ?"/>
<DataGridTextColumn Header="Operator" Binding="Binding ?"/>
<DataGridTextColumn Header="Interest" Binding="Binding ?"/>
<DataGridTextColumn Header="Type" Binding="Binding ?"/>
</DataGrid.Columns>
</DataGrid>
如果我在第一列中使用Binding="Binding Value[0]
,那么我会在我的列中得到一个“行”值,但我希望它反过来。我也尝试过使用Binding="Binding Asset.Partners[Company]"
,但没有奏效。
任何帮助表示赞赏。
【问题讨论】:
不要在绑定中使用字典。出于多种不同的原因,它们很糟糕。创建一个特定的类型来保存您的键/值对并将它们放入 ObservableCollection。如果你是一个书呆子程序员,你可以创建一个 KeyedCollection我个人会创建一个对象模型来表示您的数据,并绑定到这些对象的集合。
public class MyObject
public string Company get; set;
public string Operator get; set;
public string Interest get; set;
public string Type get; set;
和
public MainViewModel()
var partners = new ObservableCollection<MyObject>()
new MyObject("company1", "false", "40%", "type1"),
new MyObject("company2", "true", "60%", "type2")
;
...
我认为普通 DataGrid 无法满足您的要求,因为它将内容读取为“对于集合中的每一行,创建一个 DataRow 并将 DataContext 分配给该行”。在你的情况下,每一行代表整个数据网格,所以这对你不起作用。
【讨论】:
出于性能考虑,我想尝试避免为我的资产类型的属性创建额外的对象模型。我已经有了一项服务,它以字典格式返回大量数据,所以我真的希望我可以直接绑定这些数据。假设我想避免使用额外的对象模型,我最好以 DataTable 格式从服务返回数据吗?还是重组我的字典? @Courlu 一个新的对象模型应该不会影响性能并使您的代码更易于阅读,但是可以。您可以重组您的字典,以便字典中的每个项目都是每行的所有数据(new List<string> "company1", "false", "40%", "type1"
并与Binding Value[0]
绑定,或者使用 DataTable。就这两者而言,我更喜欢仅用于结构化数据的数据表并且不需要对 XAML 进行硬编码。
好的,非常感谢您的帮助!但是在创建大量附加对象时不会对性能产生影响吗?例如。分配内存并运行构造函数?
@Courlu 不,如果将内容解析为字典或数据表实际上可能会更糟,尤其是在转换数据类型时。
@Will - Rachel 已经向我证实了这一点。你的傲慢言论没有增加任何价值。【参考方案2】:
@courlu 使用字典也可以实现一切,但大多数人更喜欢 ObservableCollection。 字典也继承了 IEnumerable 和 ICollection,它们告诉你字典也可以分配为 wpf 控件的 ItemSource。
.Net 提供的 Dictionary 通用代码: 公共类字典:IDictionary,ICollection>,IEnumerable>,IEnumerable,IDictionary,ICollection,IReadOnlyDictionary,IReadOnlyCollection>,ISerializable,IDeserializationCallback
因此您需要在代码中进行以下更改
<DataGrid x:Name="dg" ItemsSource="Binding Asset.Partners.Values" AutoGenerateColumns="false">
<DataGrid.Columns>
<DataGridTextColumn Header="Company" Binding="Binding Company"/>
<DataGridTextColumn Header="Operator" Binding="Binding Operator"/>
<DataGridTextColumn Header="Interest" Binding="Binding Interest"/>
<DataGridTextColumn Header="Type" Binding="Binding Type"/>
</DataGrid.Columns>
如果你想要 TwoWay 模式绑定然后继承字典类这个 2 接口 INotifyCollectionChanged,INotifyPropertyChanged 它将支持 2 路绑定也像 ObservableCollection。
【讨论】:
以上是关于WPF MVVM 将 Dictionary<String, List<String>> 绑定到数据网格的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Dictionary<enum, bool> 双向绑定到 WPF 中的 ListView 列?
无法使用 MVVM 将 WPF ChartPlotter 绑定到视图