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 の各行に異なるクラスをバインドしたいので、セルにバインドされたオブジェクトに基づいて DataTemplateSelector を使用して DataTemplate を選択するカスタム DataGrid を使用しました。

 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