0

我创建了绑定到 DataTable 的自定义 DataGrid。
DataGrid 可能有超过 50 列,所以我启用了列虚拟化。
我的模型是这样的:

    public class Book
{
    public int Id { get; set; }
}

public class HistoricalBook : Book
{
    public DateTime HistoricalPeriod { get; set; }
}

public class CriminalBook : Book
{
    public string MainCharacter { get; set; }
}

这就是我填充 DataTable 的方式

 public class MainViewModel : ViewModelBase
{
    private DataTable _table;
    public DataTable Table
    {
        get { return _table; }
        set
        {
            if (value == _table) return;
            _table = value;
            RaisePropertyChanged(() => Table);
        }
    }
    public MainViewModel()
    {
        Initiate();
    }

    private void Initiate()
    {
        Table = new DataTable("BookTable");
        for (int i = 0; i < 20; i++)
            Table.Columns.Add(new DataColumn(String.Format("Column{0}", i), typeof (Book)));

        Table.Columns.Add(new DataColumn("B", typeof (Book)));

        for (int j = 0; j <= 80; j++)
        {
            var books = new Book[20];
            if (j == 0)
            {
                for (int i = 0; i < 20; i++)
                    books[i] = new HistoricalBook
                                   {
                                       Id = i,
                                       HistoricalPeriod = DateTime.Now.AddDays(i)
                                   };
            }
            else
            {
                for (int i = 0; i < 20; i++)
                    books[i] = new CriminalBook
                                   {
                                       Id = i,
                                       MainCharacter = string.Format("Name {0}", i)
                                   };
            }
            Table.Rows.Add(books);
        }
    }
}

因为我想将不同的类绑定到我的 DataGrid 的每一行,所以我使用了自定义 DataGrid,它使用基于有界对象到单元格的 DataTemplateSelector 选择 DataTemplate。

 public class MyDataGrid : DataGrid
{
    public static readonly DependencyProperty CellTemplateSelectorProperty =
        DependencyProperty.Register("Selector", typeof (DataTemplateSelector), typeof (MyDataGrid), new FrameworkPropertyMetadata(null));
    public DataTemplateSelector CellTemplateSelector
    {
        get { return (DataTemplateSelector) GetValue(CellTemplateSelectorProperty); }
        set { SetValue(CellTemplateSelectorProperty, value); }
    }

            public static readonly DependencyProperty CellEditTemplateSelectorProperty =
        DependencyProperty.Register("EditSelector", typeof (DataTemplateSelector), typeof (MyDataGrid), new FrameworkPropertyMetadata(null));
    public DataTemplateSelector CellEditTemplateSelector
    {
        get { return (DataTemplateSelector) GetValue(CellEditTemplateSelectorProperty); }
        set { SetValue(CellEditTemplateSelectorProperty, value); }
    }


    protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
    {
        e.Cancel = true;
        var column = new DataRowColumn(e.PropertyName) {Header = e.Column.Header, CellTemplateSelector = CellTemplateSelector,
        CellEditingTemplateSelector = CellEditTemplateSelector
        };
        Columns.Add(column);

    }
}
public class DataRowColumn : DataGridTemplateColumn
{
    public string ColumnName { get; private set; }
    public DataRowColumn(string column)
    {
        ColumnName = column;
    }
    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        var row = dataItem as DataRowView;
        if (row != null)
        {
            object item = row[ColumnName];
            cell.DataContext = item;
            FrameworkElement element = base.GenerateElement(cell, item);
            return element;
        }

        return new FrameworkElement();
    }
}

XAML:

    <Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.Resources>

        <helper:BookTemplateSelector x:Key="bookTemplateSelector">
            <helper:BookTemplateSelector.CriminalBookTemplate>
                <DataTemplate>
                    <Label Content="{Binding Id}"
                             Width="50" />
                </DataTemplate>
            </helper:BookTemplateSelector.CriminalBookTemplate>
            <helper:BookTemplateSelector.HistoricalBookTemplate>
                <DataTemplate>
                    <Label Content="{Binding HistoricalPeriod}"
                             Width="50" />
                </DataTemplate>
            </helper:BookTemplateSelector.HistoricalBookTemplate>
        </helper:BookTemplateSelector>

        <helper:BookTemplateSelector x:Key="editBookTemplateSelector">
            <helper:BookTemplateSelector.CriminalBookTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding Id}"
                             Width="50" />
                </DataTemplate>
            </helper:BookTemplateSelector.CriminalBookTemplate>
            <helper:BookTemplateSelector.HistoricalBookTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding HistoricalPeriod}"
                             Width="50" />
                </DataTemplate>
            </helper:BookTemplateSelector.HistoricalBookTemplate>
        </helper:BookTemplateSelector>
    </Grid.Resources>
    <control:MyDataGrid Grid.Row="0"
                        HeadersVisibility="None"
                        ItemsSource="{Binding Table}"
                        AutoGenerateColumns="True"
                        CellTemplateSelector="{StaticResource bookTemplateSelector}"
                        CellEditTemplateSelector="{StaticResource editBookTemplateSelector}"
                        EnableColumnVirtualization="True"
                        EnableRowVirtualization="True"

                        VirtualizingStackPanel.IsVirtualizing="True"
                        VirtualizingStackPanel.VirtualizationMode="Standard">
    </control:MyDataGrid>



</Grid>

乍一看 DataGrid 工作正常: 在此处输入图像描述

滚动数据后显示不正确:

在此处输入图像描述

源代码

4

0 回答 0