如何使用反射在WPF DataGrid中自动生成列?

时间:2013-06-20 18:16:53

标签: c# wpf datagrid system.reflection

我将DataGrid绑定到从IMyInterface派生的不同类型的对象集合。我需要根据对象的实际类型对DataGrid进行分组,并根据每种类型的属性自动生成每个组中的colulmns,因为类型具有不同的属性。

请帮忙。

我正在添加一些现有代码:

XAML:

<Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type GroupItem}">
                <Expander IsExpanded="False" 
                    Background="White"
                    Foreground="Black">
                    <Expander.Header>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Name}"/>
                            <TextBlock Text="{Binding Path=ItemCount}" Padding="10, 0, 10, 0"/>
                            <TextBlock Text="Item(s)"/>
                        </StackPanel>
                    </Expander.Header>
                    <ItemsPresenter />
                </Expander>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

...

<DataGrid Grid.Row="1" Grid.Column="2" Name="DgPendingMessages" ItemsSource="{Binding }" AutoGenerateColumns="False"
    IsReadOnly="True" MaxHeight="400">
    <DataGrid.GroupStyle>
        <GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
            <GroupStyle.Panel>
                <ItemsPanelTemplate>
                    <DataGridRowsPresenter />
                </ItemsPanelTemplate>
            </GroupStyle.Panel>
        </GroupStyle>
    </DataGrid.GroupStyle>

    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding TheMessage}" Header="Pending Message" />
    </DataGrid.Columns>
</DataGrid>

代码隐藏:

public class PendingMessage
{
    //public IMyInterface TheMessage { get; set; }
    public string TheMessage { get; set; }
    public string MessageType { get; set; }
}

PendingMessage是我的模型类,它包含真实Message对象的字符串表示形式和Message对象的原始类型(用于通过它对DataGrid进行分组)。

Message对象可以是从IMyInterface派生的任何类型。

var collectionPendingMessages = new ListCollectionView(PendingMessages);
collectionPendingMessages.GroupDescriptions.Add(new PropertyGroupDescription("MessageType"));
DgPendingMessages.ItemsSource = collectionPendingMessages;

而不是真正的Message对象的字符串表示,我希望有这样的东西:

A型:3件

列N |列Z |第X列|第T栏

数据|数据|数据|数据

数据|数据|数据|数据

数据|数据|数据|数据


B型:4件

列N |列S |第U栏

数据|数据|数据

数据|数据|数据

数据|数据|数据

数据|数据|数据


C型:3件

列N |列Z |第X列|列T |第U栏

数据|数据|数据|数据|数据

数据|数据|数据|数据|数据

数据|数据|数据|数据|数据

1 个答案:

答案 0 :(得分:1)

我之前已经解决过这个问题了。如果您基本上使用XAML作为视图,那么对我有用的一个选项是在运行时动态生成您需要的XAML。感觉有点难看,但似乎确实有效。

这是我在其中一个项目中的代码隐藏课程。希望它足够接近您的问题:

public partial class SetupPanel : UserControl
{
    public SetupPanel()
    {
        InitializeComponent();
    }

    protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
    {
        AddParticipantGridViewColumns();
        base.OnRender(drawingContext);
    }

    public void AddParticipantGridViewColumns()
    {
        ...
        for (var blockIndex = 0; blockIndex < blockColumnCount; blockIndex++)
        {
            var column = BuildParticipantGridViewColumn(blockIndex);
            dataGrid.Columns.Add(column);
        }
    }

    private DataGridTemplateColumn BuildParticipantGridViewColumn(int blockIndex)
    {
        var columnXaml = string.Format(@"
            <DataGridTemplateColumn
                xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
                xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
                Header=""Block {1}"">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text=""{{Binding BlockViewModels[{0}].ConditionLabel}}""
                                   Foreground=""{{Binding BlockViewModels[{0}].TextBrush}}"" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>",
            blockIndex, blockIndex + 1);
        var column = (DataGridTemplateColumn)XamlReader.Parse(columnXaml);
        return column;
    }
}

<强>更新

再次阅读您的问题,您可能需要做的就是使用AutoGenerateColumns="true"作为您的DataGrid。但是,只有在您不想自定义列的外观时才能使用此功能。


更新2

查看更新后的问题,看起来您可能真正需要做的就是将消息放入DataTable对象中,这样就可以构建列并在运行时动态填充数据。然后,您可以使用AutoGenerateColumns,或者,如果您需要更多自定义,请使用XAML生成(如上所述)将列添加到DataGrid。