是否可以将包含List<String>的List<Object>绑定到DataGrid?

6
我的问题是如何将一个包含List<String>List<Object>绑定到WPF中的DataGrid。假设类看起来像这样:
Class Student
{
         String Name;
         List<String> Marks;
}

假设我有一个 List<Student>,但是如何将其绑定到数据源中的数据网格呢?
我确定这个 DataGrid.DataSource=List<Student> 不会按预期工作。
这就是我想要的效果: enter image description here

你想展示哪个学生的成绩?我的问题是,你想绑定当前选择的学生的成绩吗? - Sivasubramanian
我有一个包含5个学生的List<Student>对象,每个学生有5门科目的成绩。 - Usual Suspect
你想同时显示所有学生及其姓名,还是根据任何选择显示任何一个学生的成绩? - Sivasubramanian
你可以使用ListView,并在其中创建DataGrid。DataGrid的源是一个列表(二维)。将List<Student>绑定到ListView并将Marks绑定到DataGrid。 - Rang
@Sivasubramanian 不是所有的学生。 - Usual Suspect
显示剩余3条评论
4个回答

5

here you go

    <DataGrid ItemsSource="{Binding Students}"
              AutoGenerateColumns="False"
              CanUserAddRows="False">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Name}"
                                Header="Name" />
            <DataGridTextColumn Binding="{Binding Marks[0]}"
                                Header="Mark1" />
            <DataGridTextColumn Binding="{Binding Marks[1]}"
                                Header="Mark2" />
            <DataGridTextColumn Binding="{Binding Marks[2]}"
                                Header="Mark3" />
        </DataGrid.Columns>
    </DataGrid>

同时将类名更改为

    class Student
    {
        public String Name { get; set; }
        public List<String> Marks { get; set; }
    }

注意,我为您的变量创建了公共属性

结果

样例

可变列

您可以拥有可变数量的列,但不是每一行都可以

方法1 在XAML中硬编码最大列数,因此如果某一行没有该列的值,则该列将保持为空白

例如

网格样例2

我添加了另一列以清楚地演示

<DataGridTextColumn Binding="{Binding Marks[3]}"
                    Header="Mark4" />

其他方法涉及通过代码后台或使用附加属性来在运行时生成列。


我希望每个学生的分数都是相同的,如果不是,那么你期望在空缺的位置看到空白还是0?如果你知道最大分数列,你可以简单地定义所有,或者也许你可以通过在代码后台生成列或使用附加属性行为来获得更好的控制。 - pushpraj
XAML 本身可能无法完成此操作,因为 Marks 是一种集合类型。如果您需要这样做,那么您可能需要为 Student 类定义一些属性描述符,以便 XAML 能够发现这些属性。您是否希望采用这种方法? - pushpraj
是的,我认为在XAML中会很不错。 - Usual Suspect
你的代码可能会出现问题。如果一条记录没有任何分数,那么你将绑定到空值。也许会抛出IndexOutOfRangeException异常。其他部分看起来都很好。 - klm_
这些是绑定错误,会导致单元格产生空值。您可以选择在绑定中定义回退值以显示在空白处,例如“N/A”等,这样UI就不会出现任何错误。上面的示例来自我的测试。 - pushpraj
显示剩余2条评论

3
您可以像这样尝试。
<DataGrid ItemsSource="{Binding lstStu}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="name" Binding="{Binding Name}"/>
                <DataGridTemplateColumn Header="list">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ListBox ItemsSource="{Binding Marks}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

如果您不想在列表中显示标记,并且您有固定数量的标记,可以按照以下方式操作:

<DataGridTextColumn Header="name" Binding="{Binding Name}"/>
<DataGridTextColumn Header="mark1" Binding="{Binding Marks[0]}"/>
<DataGridTextColumn Header="mark2" Binding="{Binding Marks[1]}"/>

2

您需要使用以下代码:

Class Student
{
         String Name;
         List<String> Marks;
}


 private ObservableCollection<Student> _student=new ObservableCollection<Student>();

    public ObservableCollection<Student> student
    {
        get { return _student; }
        set { _student = value; }
    }

您的Itemsource看起来像:
<DataGrid ItemsSource="{Binding student}">
        <DataGrid.ItemTemplate>
            <DataTemplate>
                <DataGrid ItemsSource="{Binding Marks}"></DataGrid>
            </DataTemplate>
        </DataGrid.ItemTemplate>
    </DataGrid>

它会扩展List<Marks>并将其放入列中吗? - Usual Suspect
抱歉,我明白了。但是这只适用于一个学生,那么对于一个学生列表呢? - Usual Suspect
使用 List<Student> 替换 <Student> - Ashish-BeJovial

1
首先,您需要在模型中使用公共属性而不是字段。就像这样:

public class Student
{
         public String Name {get;set;}
         public List<String> Marks {get;set;}
}

然后为网格提供数据上下文。在代码后台添加类似以下的内容:

var StudentsList = new List<Student>();
//populate the list.....    
DataContext=StudentsList;

最后一件事是将DataContext与xaml中的控件绑定。就像在其他答案中一样:
 <ListView ItemsSource="{Binding StudentsList}">
        <ListView.ItemTemplate>
                <DataTemplate>
                       <DataGrid ItemsSource="{Binding Marks}" />
                </DataTemplate>
        </ListView.ItemTemplate>
 </ListView>

很遗憾,这个不起作用。数据网格显示了一个名为“Marks”的列,但在行中却显示为“Collection”。 - Philip Gierszal

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