DataGrid CustomColumn绑定

时间:2014-06-18 10:19:18

标签: c# wpf datagrid

我有一个datagrid,其中列被动态填充。我必须在代码中执行,因为用户可以通过自定义列设置系统添加列/删除列/修改列属性。

我已经创建了一个附加属性作为依赖属性,如下所示:

public class DataGridColumnBehavior
{
    public static readonly DependencyProperty ColumnsSourceProperty =
        DependencyProperty.RegisterAttached("ColumnsSource",
                                            typeof (ObservableCollection<ColumnDescriptor>),
                                            typeof (DataGridColumnBehavior),
                                            new UIPropertyMetadata(null, ColumnsSourcePropertyChanged));

    private static void ColumnsSourcePropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        var dataGrid = source as DataGrid;
        var columnDescriptors = e.NewValue as ObservableCollection<ColumnDescriptor>;

        if (dataGrid != null && columnDescriptors != null && columnDescriptors.Any())
        {
            dataGrid.Columns.Clear();

            columnDescriptors.ToList().ForEach(col =>
                {
                    var gridColumn = CreateDataGridColumn(col);

                    if(gridColumn != null)
                        dataGrid.Columns.Add(gridColumn); 
                });
        }
    }

    private static DataGridColumn CreateDataGridColumn(ColumnDescriptor columnDescriptor)
    {
        Type propertyType = null;

        if (columnDescriptor.ParentDtoType != null)
            propertyType = columnDescriptor.ParentDtoType.GetProperty(columnDescriptor.DataPropertyName).PropertyType;

        DataGridBoundColumn returnColumn;

        if (propertyType == typeof (bool))
        {
            returnColumn = new DataGridCheckBoxColumn();
        }
        else if (propertyType == typeof (string) && columnDescriptor.LookupOn)
        {
            returnColumn = new DataGridLookupColumn();                
        }
        else if (propertyType == typeof (DateTime?) || propertyType == typeof(DateTime))
        {
            returnColumn = new DataGridDateColumn();
        }
        else
        {
            returnColumn = new DataGridTextColumn();
        }

        returnColumn.Header = columnDescriptor.HeaderText;
        returnColumn.Width = columnDescriptor.Width;
        returnColumn.Binding = new Binding(columnDescriptor.DataPropertyName) { UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, Mode = BindingMode.TwoWay };
        returnColumn.IsReadOnly = columnDescriptor.TextReadOnly;
        returnColumn.Visibility = columnDescriptor.Visible ? Visibility.Visible : Visibility.Collapsed;

        return returnColumn;
    }

    public static void SetColumnsSource(DependencyObject element, ObservableCollection<DataGridColumn> value)
    {
        element.SetValue(ColumnsSourceProperty, value);
    }

    public static ObservableCollection<DataGridColumn> GetColumnsSource(DependencyObject element)
    {
        return (ObservableCollection<DataGridColumn>)element.GetValue(ColumnsSourceProperty);
    }

XAML:

<DataGrid Grid.Column="6" Grid.ColumnSpan="5" Grid.RowSpan="5" Grid.Row="8" Name="KorlistaDataGrid" MaxHeight="106" behavior:DataGridColumnBehavior.ColumnsSource="{Binding ColumnsListView}" ItemsSource="{Binding MyObservableCollection}" SelectedItem="{Binding ListViewSelectedItem, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" AutoGenerateColumns="False">
            <DataGrid.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="XXX" Command="{Binding ContextMenuCommand}" IsEnabled="{Binding CMSIsEnabled, UpdateSourceTrigger=PropertyChanged}"></MenuItem>
                </ContextMenu>
            </DataGrid.ContextMenu>
        </DataGrid>

我的自定义列:

public class DataGridDateColumn : DataGridTextColumn
{
    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        var dataGridBoundColumn = cell.Column as DataGridBoundColumn;
        var datePicker = new DatePicker { Width = 50, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center };

        if (dataGridBoundColumn != null)
        {
            datePicker.SetBinding(TextBox.TextProperty, dataGridBoundColumn.Binding);

            var bindingExpression = datePicker.GetBindingExpression(TextBox.TextProperty);

            if (bindingExpression != null)
            {
                bindingExpression.UpdateSource();
                bindingExpression.UpdateTarget();
            }
        }

        return datePicker;
    }
}

一切看起来都很棒,我的列就像我想要的那样,我的itemssource中的所有绑定值都被视为预期。

最后我的问题:如何在这里配置绑定,以便:

  1. 绑定值显示在editmode
  2. 中的datepicker中
  3. 如果我更改editmode中的值(手动或通过选择器),我显然希望在我的数据源中更新该值并在我离开editmode后显示在viewmode中。
  4. 提前致谢!

1 个答案:

答案 0 :(得分:1)

好的,我自己解决了这个问题:)

这有效

protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
{
    var dataGridBoundColumn = cell.Column as DataGridBoundColumn;
    var datePicker = new DatePicker { Width = 50, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center };
    var cellContent = cell.Content as TextBlock;

    if (dataGridBoundColumn != null)
    {
        var bindingExpression = (cell.Content as TextBlock) != null ? BindingOperations.GetBindingExpression(cellContent, TextBlock.TextProperty) : null;

        if (bindingExpression != null)
        {
            var newBindning = new Binding(bindingExpression.ParentBinding.Path.Path)
                {
                    UpdateSourceTrigger = bindingExpression.ParentBinding.UpdateSourceTrigger, Mode = bindingExpression.ParentBinding.Mode
                };

            datePicker.SetBinding(DatePicker.TextProperty, newBindning);
        }
    }

    return datePicker;
}