Рассматривали ли вы создание эффекта DataGrid с помощью ItemsControl? Что-то вроде:
<ItemsControl ItemsSource="{Binding}" Name="IC1" VirtualizingStackPanel.IsVirtualizing="True" ScrollViewer.CanContentScroll="True">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<Border
BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
SnapsToDevicePixels="True">
<ScrollViewer
Padding="{TemplateBinding Control.Padding}"
Focusable="False">
<ItemsPresenter
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="9*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="ID" Grid.Column="0" Grid.Row="0"/>
<TextBlock Grid.Column="0" Grid.Row="1" Text="{Binding Path=id}"/>
<ItemsControl Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" ItemsSource="{Binding}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=columnName}" Width="100" />
<TextBox Text="{Binding Path=value}" Width="100" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Я заполнил некоторые тестовые данные (извините, но в VB):
Property PersonList As New ObservableCollection(Of Person)
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
For x As Integer = 1 To 500
Dim P1 As New Person With {.id = "SE" & x}
P1.Add(New DataObject With {.columnName = "First Name", .value = "Simon"})
P1.Add(New DataObject With {.columnName = "Last Name", .value = "Evans"})
P1.Add(New DataObject With {.columnName = "DOB", .value = "03/03/1980"})
Dim P2 As New Person With {.id = "RE" & x}
P2.Add(New DataObject With {.columnName = "First Name", .value = "Ruth"})
P2.Add(New DataObject With {.columnName = "Last Name", .value = "Evans"})
P2.Add(New DataObject With {.columnName = "DOB", .value = "11/02/1979"})
PersonList.Add(P1)
PersonList.Add(P2)
Next
IC1.DataContext = PersonList
End Sub
Это 1000 строк, но поскольку в элементе управления используется виртуализация, лагов нет.
EDIT
Не знаю, является ли лучший способ, но я бы предложил добавить свойство Int width в ваш класс DataObject и привязать к нему ширину TextBlocks & TextBoxes во втором ItemsControl.
Затем, используя приведенный ниже фрагмент кода, вычислите максимальную требуемую ширину (слава WPF эквивалентен TextRenderer ):
public static Size MeasureTextSize(string text, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, double fontSize)
{
FormattedText ft = new FormattedText(text,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface(fontFamily, fontStyle, fontWeight, fontStretch),
fontSize,
Brushes.Black);
return new Size(ft.Width, ft.Height);
}
(Я использовал детали шрифта для окна, но вы, конечно, можете указать другие детали, если вы вводите текстовые поля.)
Затем я написал это немного, чтобы просмотреть данные и установить ширину (извините, обратно в VB):
If PersonList.Count > 0 Then
Dim MaxLengths(PersonList(0).Count - 1) As Integer
For i As Integer = 0 To MaxLengths.Count - 1
MaxLengths(i) = 70 'Set Minimum width to accomodate Headers
Next
For Each P As Person In PersonList
For i As Integer = 0 To P.Count - 1
Dim BoxSize As Size = MeasureTextSize(P(i).value, FontFamily, FontStyle, FontWeight, FontStretch, FontSize)
If BoxSize.Width > MaxLengths(i) Then MaxLengths(i) = BoxSize.Width + 6 'to allow for padding
Next
Next
For Each P As Person In PersonList
For i As Integer = 0 To P.Count - 1
P(i).width = MaxLengths(i)
Next
Next
End If