Ich habe eine WPF DataGrid
, gebunden an eine DataTable
, die eine variable Anzahl von Spalten enthalten kann. Diese DataTable
kann zur Laufzeit das Schema und die Daten ändern, wenn der Benutzer eine neue Datendatei zum Laden in die App auswählt (im folgenden Beispiel wird dies durch Klicken auf die Schaltfläche Load Data simuliert).Wie kann ich die Spaltengröße bei Scroll in einem WPF DataGrid mit aktivierter Zeilenvirtualisierung stoppen?
Ich habe die Spaltenbreite auf Auto
eingestellt, so dass Spalten automatisch die Größe anpassen, um ihren Kopftext oder den längsten Teil des Zeileninhalts in der Spalte (was immer größer ist) zu passen. Hier ist die MainWindow.xaml aus meinem Beispiel:
<Window x:Class="analog.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:analog"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="600">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="loadData" Grid.Row="0" Margin="0" Content="Load Data" Click="loadData_Click" VerticalAlignment="Top" />
<DataGrid x:Name="dataGrid" Grid.Row="1" Margin="0" IsReadOnly="True" CanUserAddRows="False" ColumnWidth="Auto" SelectionUnit="Cell" />
</Grid>
</Window>
Und hier ist MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void loadData_Click(object sender, RoutedEventArgs e)
{
var data = new DataTable();
data.Columns.Add("A", typeof(string));
data.Columns.Add("B", typeof(string));
data.Columns.Add("C", typeof(string));
Enumerable.Range(1, 50).ToList().ForEach(i => {
var row = data.NewRow();
row["A"] = "aaa";
row["B"] = "bbb";
row["C"] = "ccc";
data.Rows.Add(row);
});
var longRow = data.NewRow();
longRow["A"] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
longRow["B"] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
longRow["C"] = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";
data.Rows.Add(longRow);
dataGrid.ItemsSource = data.DefaultView;
}
}
Das funktioniert perfekt, mit der Ausnahme, dass, weil die DataGrid
Reihen virtuell sind (dh gerendert auf Anforderung, wenn die Liste gescrollt wird (im Gegensatz zu Upfront), können die Spalten nur automatisch auf den Inhalt angepasst werden, der gerade angezeigt wird.
Wenn Sie dann jedoch bis zum Ende der Liste scrollen, ändern sich die Spaltenbreiten plötzlich und dramatisch, wenn der längere Zelleninhalt sichtbar wird, was für eine wirklich schreckliche, desorientierende Benutzererfahrung sorgt.
Das Ausschalten der Zeilenvirtualisierung ist keine Option (z. B. EnableRowVirtualization="False"
), da ich einige große Datenmengen lade und die Leistung ohne sie unbrauchbar ist.
Ich verstehe die Größenbeschränkung bei der Verwendung von Virtualisierung, und ich bin ziemlich glücklich mit diesem Verhalten. Es ist vollkommen in Ordnung, wenn die Spalten nur auf den Breiten bleiben, auf die sie eingestellt sind, wenn das Raster anfänglich gerendert wird, aber ich finde einfach keinen Weg, dies zu tun!
ich einige ziemlich schreckliche Hacks habe versucht, auch diese, wo ich Schleife über die Spalten nach dem ersten machen und programmatisch die Breite in Pixel an, was Größe, die sie derzeit gerendert auf gesetzt:
foreach (DataGridColumn column in dataGrid.Columns)
{
column.Width = new DataGridLength(column.ActualWidth, DataGridLengthUnitType.Pixel);
}
I Ich rufe das jetzt manuell auf, indem ich es in einen Button-Klick-Handler setze und auf die Schaltfläche klicke, nachdem die ersten Daten gerendert wurden - aber das hat keinerlei Auswirkungen, und die Größenänderung geschieht immer noch, wenn ich zu den längeren Werten komme.
Also, wie kann ich die Größenänderung der Spalten stoppen, wenn ich die DataGrid
scrollen?
Hmm, das funktioniert nicht in meinem Fall. Dies ist ziemlich genau das, was ich gerade mache, außer dass die Schleife über die Spalten derzeit in einem Button-Klick-Handler (den ich gerade manuell anklicke, nachdem das Element geladen wurde) statt in dem Data-Grid-Load-Event-Handler erfolgt. –
Der offensichtliche Unterschied zwischen Ihrem Beispiel und meinem Code ist, dass Sie die Spalten und Daten zur Kompilierzeit deklarieren (und 'AutoGenerateColumns =" False "'), während in meiner App das Grid dynamisch aus dem Schema und den Daten von erstellt wird die aktuell an das Steuerelement gebundene 'DataTable' (die sich auch zur Laufzeit ändern kann). Entschuldigung, wenn ich das in der Frage klarer gemacht hätte ... jetzt bearbeitet. –
Vielleicht könnten Sie dann eine reproduzierbare Probe Ihres Problems zur Verfügung stellen? Sie sollten dies lesen: http://stackoverflow.com/help/how-to-ask – mm8