简体   繁体   English

数据绑定DataGrid与自定义列标题

[英]Data bound DataGrid with custom column headers

My question seems rather simple: 我的问题似乎很简单:

How can one add custom headers to a data bound DataGrid in WPF? 如何在WPF中向数据绑定DataGrid添加自定义标头?

Why am I asking this question? 我为什么问这个问题? Well, because I've fitted my DataGrid (which is generated in code-behind) with a dynamic itemssource, bound to an ienumerable 'list'. 好吧,因为我已经将我的DataGrid(在代码隐藏中生成)与动态itemssource相匹配,绑定到一个不可数的“列表”。 This works perfectly fine, although it uses the property names as column headers. 虽然它使用属性名称作为列标题,但这完全正常。

To improve readability I simply want to assign custom headers to the columns, however... My idea was to supply a datagrid with the columns already defined, and let the itemssource fill the rows. 为了提高可读性,我只想将自定义标题分配给列,但是......我的想法是为数据网格提供已定义的列,并让itemssource填充行。 But itemssource deals with the rows, as well as the columns. 但是itemssource处理行以及列。

I hope you can see my problem here. 我希望你能在这里看到我的问题。 Help is greatly appreciated! 非常感谢帮助!

Handle the AutoGeneratingColumn event of the DataGrid and then you can create some kind of map between the default column names (Property names) and your custom headers. 处理DataGrid的AutoGeneratingColumn事件,然后您可以在默认列名称(属性名称)和自定义标题之间创建某种映射。

For example: 例如:

string headername = e.Column.Header.ToString();

if (headername == "MiddleName")
     e.Column.Header = "Middle Name";

Edit: taken from MDSN 编辑: 取自MDSN

The DataGrid class has a property to configure the column generation behavior, called "AutoGenerateColumns" ( link ). DataGrid类具有用于配置列生成行为的属性,称为“AutoGenerateColumns”( 链接 )。 To disable this behavior just set it to false. 要禁用此行为,只需将其设置为false。

You have a better control of the shape of your DataGrid if you do it in xaml. 如果在xaml中执行此操作,则可以更好地控制DataGrid的形状。 An example: 一个例子:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="MainWindow"
    Width="525"
    Height="350">
<Grid>                  
    <DataGrid AutoGenerateColumns="False" >
        <DataGrid.Columns>              
            <DataGridTextColumn Header="MyHeader1" Binding="{Binding MyProperty1}"/>
            <DataGridTextColumn Binding="{Binding MyProperty2}">
                <DataGridTextColumn.Header>
                    <Button Content="A button"/>
                </DataGridTextColumn.Header>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

As you can see, the "Header" property of a column definition will accept any content, texts or controls, if you want to customize it further. 如您所见,如果要进一步自定义列定义的“Header”属性,则它将接受任何内容,文本或控件。

EDIT 编辑

An example of how to do it from the code behind, in the Window's Loaded event: 在Window的Loaded事件中,如何从后面的代码中执行此操作的示例:

void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        var dataGrid = new DataGrid();
        dataGrid.AutoGenerateColumns = false;

        // For each column you want
        var column1 = new DataGridTextColumn();
        column1.Header = "MyHeader";
        column1.Binding = new Binding("MyProperty");
        dataGrid.Columns.Add(column1);

        // LayoutRoot is the main grid of the Window
        this.LayoutRoot.Children.Add(dataGrid);


        // Let's test to see if the binding is working
        IEnumerable<DummyClass> testEnumerable = new List<DummyClass>(){
            new DummyClass(){MyProperty= "Element1"},
            new DummyClass(){MyProperty= "Element2"},
        };

        dataGrid.ItemsSource = testEnumerable;
    }

If you're creating a DataGrid from code-behind, you can specify everything that you bind with DataContext and Bindings . 如果从代码隐藏创建DataGrid,则可以指定与DataContextBindings

Let's say we have a DataGrid myDataGrid . 假设我们有一个DataGrid myDataGrid

Bind the ItemsSource to myDataGrid : 将ItemsSource绑定到myDataGrid

 Binding dataGridItemsSourceBinding = new Binding("MyItemsSourceName");
 myDataGrid.SetBinding(DataGrid.ItemsSourceProperty, datagridItemsSourceBinding);

Create a DataGridTemplateColumn 创建DataGridTemplateColumn

 DataGridTemplateColumn templatecolumn = new DataGridTemplateColumn() {
      Header = "myColumnName", // Add the name of your column here
 };

Create the Data Template for when you are displaying the value in the DataCell for the DataGrid Column 当您在DataCrid列的DataCell中显示值时,创建数据模板

 // Displaying Template for when you display the DataCell in the DataGridColumn
 // Create a Data Template for when you are displaying a DataGridColumn
 DataTemplate textBlockTemplate = new DataTemplate();
 // Create a Framework Element for the DataGridColumn type (In this case, a TextBlock)
 FrameworkElementFactory textBlockElement = new FrameworkElementFactory(typeof(TextBlock));
 // Create a Binding to the value being displayed in the DataGridColumn
 Binding textBlockBinding = new Binding("myPropertyName");
 // Assign the Binding to the Text Property of the TextBlock
 textBlockElement.SetBinding(TextBlock.TextProperty, textBlockBinding);
 // Set the DataGridColumn to stretch to fit the text
 textBlockElement.SetValue(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
 // Add the TextBlock element to the Visual Tree of the Data Template
 textBlockTemplate.VisualTree = textBlockElement;
 // Add the Data Template to the DataGridColumn Cell Template
 templatecolumn.CellTemplate = textBlockTemplate;

Create the Data Template for when you are editing the value in the DataCell for the DataGrid Column 在DataCrid列的DataCell中编辑值时,创建数据模板

 // Editing Template for when you edit the DataCell in the DataGridColumn
 // Create a Data Template for when you are displaying a DataGridColumn
 DataTemplate textBoxTemplate = new DataTemplate();
 // Create a Framework Element for the DataGrid Column type (In this case, TextBox so the user can type)
 FrameworkElementFactory textBoxElement = new FrameworkElementFactory(typeof(TextBox));
 // Create a Binding to the value being edited in the DataGridColumn
 Binding textBoxBinding = new Binding("myPropertyName");
 // Assign the Binding to the Text Property of the TextBox
 textBoxElement.SetBinding(TextBox.TextProperty, textBoxBinding);
 // Set the DataGridColumn to stretch to fit the text
 textBlockElement.SetValue(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
 // Add the TextBox element to the Visual Tree of the Data Template
 textBoxTemplate.VisualTree = textBoxElement;
 // Add the Data Template to the DataGridColumn Cell Editing Template
 templatecolumn.CellEditingTemplate = textBoxTemplate;

Add the completed DataGridColumn to your DataGrid 将完成的DataGridColumn添加到DataGrid

 // Add the completed DataGridColumn to your DataGrid
 myDataGrid.Columns.Add(templateColumn);

If using AutoGenerate see link below 如果使用AutoGenerate,请参阅下面的链接

DataGrid.AutoGenerateColumns DataGrid.AutoGenerateColumns

Or don't AutoGenerate and build the binding. 或者不要AutoGenerate并构建绑定。
If the columns are dynamic then must you code behind. 如果列是动态的,那么你必须在后面编码。
If the columns are statics then can use XAML. 如果列是静态的,那么可以使用XAML。

<DataGrid Name="DG1" ItemsSource="{Binding}" AutoGenerateColumns="False" >
     <DataGrid.Columns>
          <DataGridTextColumn Header="First Name"  Binding="{Binding FirstName}"/>   

If you know that every time you will get same data then you can define columns headers and forget about rows. 如果您知道每次获得相同的数据,那么您可以定义列标题并忘记行。 I assume that you have list of object of same type and it means you will have same properties to display in each row. 我假设你有相同类型的对象列表,这意味着你将在每一行中显示相同的属性。 Things will be simple if you will provide some example of your Enumerable. 如果您将提供您的Enumerable的一些示例,事情将变得简单。

You can define column headers in XAML file and also in properties of DataGrid in Columns Property. 您可以在XAML文件中定义列标题,也可以在列属性中的DataGrid属性中定义列标题。

Before doing this you have to bind you list with itemsource of Datagrid. 在执行此操作之前,您必须使用Datagrid的itemsource绑定列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM