WPF Datagrid绑定自定义列标题 [英] WPF Datagrid binding custom column headers

查看:228
本文介绍了WPF Datagrid绑定自定义列标题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找出如何使用MVVM模式将WPF DataGrid的列标题和主数据绑定到数据源。我正在寻找的结果如下所示:

I am trying to figure out how to bind a WPF DataGrid's column header and main data to a data source using an MVVM pattern. The result I'm looking for would look like this:

alt text http://brian.vallelunga.com/files/datagrid-custom-headers.PNG

我已经成功设置了标题这里,但我不确定如何绑定标头中的值。具体来说,复选框的IsChecked属性,组合框的选定索引和文本框的值。

I've successfully styled the headers here, but I'm unsure how to bind the values in the headers. Specifically, the IsChecked property of the check-box, the selected index of the combo box and the value of the text box.

我以前使用一个简单的DataTable来填充主网格数据,但是我将需要一些更复杂的东西来保存网格数据和每列的值。或者我可以将它们完全存储为单独的实体。

I was previously using a simple DataTable to populate the main grid data, but I'm going to need something more complex to hold both the grid data and the values for each column. Or perhaps I can store them as separate entities entirely.

那么,有没有人有任何想法我可以如何拉下这个绑定?一个限制是列必须自动生成,因为我不知道它们将在运行时之前是什么。应用程序只需从Excel电子表格中加载数据,可能会有任意数量的列。

So, does anyone have any idea of how I might pull off this binding? One limitation is that the columns must be auto-generated since I have no idea what they will be until runtime. The application simply loads the data form an Excel spreadsheet and there may be any number of columns present.

谢谢,
Brian

Thanks, Brian

推荐答案

这是我最终用MVVM模式使用的方式:

Here's what I ended up doing to use this with the MVVM pattern:

我有两套用于在我的视图模型上绑定的数据:一个用于实际网格数据,一个用于列标题。目前,这些显示为两个属性:

I have two sets of data for binding on my view model: one for the actual grid data and one for the column headers. Currently these are exposed as two properties:

// INotifyPropertyChanged support not shown for brevity
public DataTable GridData { get; set; } 
public BindingList<ImportColumnInfo> ColumnData { get; set; }

处理两组不同数据的技巧在网格中。我已经将DataGrid子类化,并为Grid提供了一个名为ColumnSource的附加数据源作为依赖属性。这是在我的视图模型上绑定到ColumnData。然后,我将每个自动生成列的标题设置为ColumnSource数据源中适当索引的数据。代码如下:

The trick to working with two differing sets of data is in the grid. I have subclassed the DataGrid and given the grid an additional data source called ColumnSource, as a dependency property. This is what is bound to the ColumnData on my view model. I then set the header of each auto-generated column to the appropriately indexed data in the ColumnSource data source. The code is as follows:

public class ImporterDataGrid : DataGrid
{
    protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
    {
        base.OnAutoGeneratingColumn(e);

        int columnIndex = this.Columns.Count;
        var column = new ImporterDataGridColumn();
        column.Header = ColumnSource[columnIndex];
        column.Binding = new Binding(e.PropertyName) { Mode = BindingMode.OneWay };
        e.Column = column;
    }

    public IList ColumnSource
    {
        get { return (IList)GetValue(ColumnSourceProperty); }
        set { SetValue(ColumnSourceProperty, value); }
    }

    public static readonly DependencyProperty ColumnSourceProperty = DependencyProperty.Register("ColumnSource", typeof(IList), typeof(ImporterDataGrid), new FrameworkPropertyMetadata(null));

}

我现在可以在模板标题中执行正常的数据绑定我的列将全部绑定在我的视图模型的ColumnData属性中的数据。

I can now perform normal data binding in the templated header of my columns, which will all bind against the data in the ColumnData property of my view model.

更新:我被要求显示我的网格的XAML。这是非常基本的,但这里是:

UPDATE: I was asked to show the XAML for my grid. It's really basic, but here it is:

<Controls:ImporterDataGrid 
    AutoGenerateColumns="True" x:Name="previewDataGrid"
    VerticalScrollBarVisibility="Visible"
    HorizontalScrollBarVisibility="Visible"
    IsReadOnly="True"
    SelectionMode="Extended"
    HeadersVisibility="Column"
    ItemsSource="{Binding PreviewData}"
    ColumnSource="{Binding PreviewColumnData}"
    Style="{StaticResource ImporterDataGridStyle}"
    Background="White" CanUserReorderColumns="False" CanUserResizeRows="False"
    CanUserSortColumns="False" AlternatingRowBackground="#FFFAFAFA" AllowDrop="True" />

这里是ImporterColumnHeaderStyle:

And here is the ImporterColumnHeaderStyle:

<Style x:Key="ImporterDataGridColumnHeaderStyle" TargetType="{x:Type toolkit:DataGridColumnHeader}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type toolkit:DataGridColumnHeader}">
                <Grid>
                    <toolkit:DataGridHeaderBorder Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" IsClickable="{TemplateBinding CanUserSort}" IsHovered="False" IsPressed="False" SortDirection="{TemplateBinding SortDirection}">
                        <Grid>
                            <CheckBox Height="16" Margin="6,6,16,0" Name="importCheckBox" IsChecked="{Binding Path=Import}" VerticalAlignment="Top">Import Column</CheckBox>
                            <StackPanel IsEnabled="{Binding Path=Import}">
                                <ComboBox Height="24" Margin="6,29,6,0" Name="columnTypeComboBox" VerticalAlignment="Top" SelectedValue="{Binding ColumnType}" ItemsSource="{Binding Source={local:EnumList {x:Type Models:ImportColumnType}}}">
                                </ComboBox>
                                <TextBox Height="23"  Margin="6,6,6,33" Name="customHeadingTextBox" VerticalAlignment="Bottom" Text="{Binding Path=CustomColumnName}" IsEnabled="{Binding ColumnType, Converter={StaticResource ColumnTypeToBooleanConverter}}" />
                            </StackPanel>
                            <TextBlock Height="20" Margin="6,0,6,7" Name="originalHeadingTextBlock" Text="{Binding Path=OriginalColumnName}" VerticalAlignment="Bottom" Foreground="Gray" />
                        </Grid>
                    </toolkit:DataGridHeaderBorder>

                    <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left">
                        <Thumb.Style>
                            <Style TargetType="{x:Type Thumb}">
                                <Setter Property="Width" Value="8"/>
                                <Setter Property="Background" Value="Transparent"/>
                                <Setter Property="Cursor" Value="SizeWE"/>
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="{x:Type Thumb}">
                                            <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </Thumb.Style>
                    </Thumb>
                    <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right">
                        <Thumb.Style>
                            <Style TargetType="{x:Type Thumb}">
                                <Setter Property="Width" Value="8"/>
                                <Setter Property="Background" Value="Transparent"/>
                                <Setter Property="Cursor" Value="SizeWE"/>
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="{x:Type Thumb}">
                                            <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </Thumb.Style>
                    </Thumb>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这篇关于WPF Datagrid绑定自定义列标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆