将Dictionary<String, List<String>>绑定到datagrid中的WPF MVVM

5

我很难将我的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

我该如何实现这个目标?我看到了这个问题,但数据的格式与我想要的相反。我希望我的键作为datagrid表头(我不介意硬编码表头,因为我认为表头属性不能使用数据绑定)。这是我的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]}",但没有成功。
非常感谢您的帮助。

2
不要在绑定中使用字典,它们因为多种原因而糟糕。创建一个特定类型来保存你的键/值对,并将它们放入ObservableCollection中。如果你是一个极客程序员,你可以创建一个实现了INotifyCollectionChanged接口的KeyedCollection<T>实现,这样就能享受到字典的好处,但不会有巨大的缺陷。 - user1228
@Will - 仅仅告诉我它们“糟糕”并没有说明原因,这并不是特别有帮助。 - Courlu
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - user1228
2个回答

3

就我个人而言,我会创建一个对象模型来表示您的数据,并绑定到这些对象的集合。

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
@Courlu 一个新的对象模型不应该影响性能并且可以使您的代码更易于阅读,但是是的。您可以重新构造字典,使字典中的每个项目都是每行的所有数据(new List<string> { "company1", "false", "40%", "type1" } 并绑定到 {Binding Value[0]}),或者使用 DataTable。就我个人而言,我更喜欢使用 DataTable,因为它具有结构化数据,不需要硬编码 XAML。 - Rachel
@Courlu 不,如果将事物解析为字典或数据表可能会更糟,特别是如果你要进行数据类型转换。 - Rachel
由于性能考虑 - user1228
2
@Will - Rachel已经向我确认了。你的傲慢言论没有增加任何价值。 - Courlu
显示剩余3条评论

1

@courlu 用字典也可以实现,但大多数人更喜欢使用ObservableCollection。字典也继承了IEnumerable和ICollection,这意味着字典也可以作为WPF控件的ItemSource进行分配。

.Net提供的Dictionary的通用代码如下: public class 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>

如果你想要双向绑定模式,那么就继承字典类,并实现INotifyCollectionChanged和INotifyPropertyChanged这两个接口,它将支持像ObservableCollection一样的双向绑定。


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