WPF MVVM如何在DataGrid中显示ObservableCollection

3
我需要在一个 DataGrid 中展示一个对象的所有信息。
ItemsCollectionA、ItemsCollectionB 和 ItemsCollectionC 都是 ObservableCollections。
我有一个 datagrid:
<DataGrid ItemsSource="{Binding Path=itemscollectionA}" HeadersVisibility="All" />

这将以网格格式显示所有属性,但 ItemsCollectionB ItemsCollectionC 显示为(集合)。
如何使 ItemsCollectionB ItemsCollectionC 向下扩展并显示它们的属性?

这是因为它不知道如何显示那些集合。它基本上在你的ItemsCollectionBItemsCollectionC上调用了.ToString()。我们需要更多信息来回答你的问题。正如@geedubb所问,你想要为这些显示什么? - gleng
现在它告诉我有一个集合,我想要显示集合中每个项目的所有值,例如显示每个项目中存在的名为“Name”或“Value”的属性(编辑以提高清晰度)。 - Oliver
@Oliver,你是否必须自动生成列?如果不是的话,这个问题就相当简单。 - Omri Btian
只是更新一下,我仍在研究这个问题,可能会找到解决方案,但不再使用数据网格,因为问题出现在集合的显示上。 - Oliver
3个回答

4
如果您可以指定列而不是自动生成它们,那么这将非常容易。以下是一个例子:
<DataGrid ItemsSource="{Binding Employees}" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding EmployeeName}"/>
        <!-- Displays the items of the first collection-->
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ListBox ItemsSource="{Binding Dogs}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

        <!-- Displays the items of the second collection-->
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ListBox ItemsSource="{Binding Cats}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

视图模型:

public class MainWindowViewModel : NotificationObject
{
    public MainWindowViewModel()
    {
        Employees = new ObservableCollection<Employee>
        {
            new Employee { EmployeeName = "Steven"},
            new Employee { EmployeeName = "Josh"},
        };
    }

    public ObservableCollection<Employee> Employees { get; set; }
}

模型:

public class Employee
{
    public Employee()
    {
        Dogs = new ObservableCollection<Dog>
        {
            new Dog { Gender = 'M'},
            new Dog { Gender = 'F'},
        };
        Cats = new ObservableCollection<Cat>
        {
            new Cat { Name = "Mitzy" , Kind = "Street Cat"},
            new Cat { Name = "Mitzy" , Kind = "House Cat"}
        };
    }

    public string EmployeeName { get; set; }

    public ObservableCollection<Dog> Dogs { get; set; }

    public ObservableCollection<Cat> Cats { get; set; }
}

public class Dog
{
    public char Gender { get; set; }

    public override string ToString()
    {
        return "Dog is a '" + Gender + "'";
    }
}

public class Cat
{
    public string Name { get; set; }

    public string Kind { get; set; }

    public override string ToString()
    {
        return "Cat name is " + Name + " and it is a " + Kind;
    }
}

考虑将ItemsCollectionA视为员工,将ItemsCollectionBItemsCollectionC视为。仍然使用ToString 来显示我重写的对象,但您可以简单地设置一个DataTemplate来决定如何显示您的模型在列中的listBox中。还请注意在DataGrid上设置AutoGenerateColumns="False"以避免创建两次列。

希望这有所帮助。


2

DataGrid只能管理一个数据源。所有的操作都是基于行的,列并不是很智能。

有两种方法:

  • 将您的数据合并到一个新对象中,包含两组字段(这可能是最简单的方法)。
  • 将两个DataGrid并排同步显示。

1

好的,看起来数据网格在这里完全不是我所需要的。我使用了一个列表框的堆栈面板,并将每个绑定的项源设置为它,它正常显示。

<StackPanel Background="white" HorizontalAlignment="Stretch"  Margin="0">
        <ListBox Background="white" x:Name="BetsListBox"  VerticalAlignment="Stretch" BorderThickness="0" 
                     ItemsSource="{Binding Path=ItemsCollectionA}" Margin="0" Width="Auto" HorizontalAlignment="Stretch" >
            <ListBox.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#F0F0F0"/>
                <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#F0F0F0"/>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
            </ListBox.Resources>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel >
                        <ListBox ItemsSource="{Binding Path=ItemsCollectionB}">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel Orientation="Horizontal">
                                        <TextBlockText="{Binding Path=varA}" />
                                        <TextBlockText="{Binding Path=varB}" />
                                        <TextBlockText="{Binding Path=varC}" />
                                    </StackPanel>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                        <ListBox BorderThickness="0" ItemsSource="{Binding Path=ItemsCollectionC}" >
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel  Orientation="Horizontal" >
                                        <TextBlock Text="{Binding Path=VarA}" ToolTip="{Binding Name}"/>
                                        <TextBlock Text="{Binding Path=VarB}" ToolTip="{Binding Name}"/>
                                        <TextBlock Text="{Binding Path=VarC}" ToolTip="{Binding Name}"/>
                                    </StackPanel>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox >
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>

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