2012-03-30 10 views
23

Wir haben derzeit eine DataGrid, die an eine DataTable gebunden ist. Es hat auch eine Template-Spalte mit einer CheckBox drin, die wir programmatisch hinzufügen. Dieser Zweck dieser Spalte ist die Verfolgung mehrerer Auswahlen in der DataGrid.DataGrid Zeile Virtualisierung Anzeige Problem

Eine Factory wird verwendet, um die CheckBox es für jede Zeile zu erstellen.

Es gibt einige Datensätze, daher wird die Zeilenvirtualisierung auf "true" gesetzt, damit die Leistung akzeptabel ist. Allerdings sehen wir ein seltsames Problem, wo, wenn wir überprüfen, einige CheckBox es in den ersten 10 Zeilen und dann nach unten scrollen etwa 50 Zeilen (das Raster hat etwa 10 Zeilen zu jeder Zeit sichtbar), gibt es eine Reihe von anderen CheckBox es das scheint zufällig überprüft zu werden.

Wenn wir die Reihenvirtualisierung deaktivieren, existiert dieses Problem nicht (aber die Leistung ist schrecklich). Gibt es einen Weg dazu? Wer weiß, was wir falsch machen können?

+0

Wenn Sie sagen, die Leistung ist schrecklich nach dem Entfernen der Virtualisierung, ist es schrecklich auf Last oder auf Bildlauf. Wenn es auf Last ist, gibt es eine Lösung, die es nicht schrecklich macht, auf der Rolle ist ein anderes Problem ... –

+0

Es ist nur auf Last. Der gesamte Leistungseinbruch betrifft die Show-Methode des Fensters, das das DataGrid enthält. Bei der Zeilenvirtualisierung werden 200ms mit 2500 Datensätzen im DataGrid angezeigt. Ohne Zeilenvirtualisierung dauert es 28 Sekunden. – WPFNewbie

+0

hinzugefügt ein wenig Code für Sie ... musste nur Leistung bei der Arbeit vor ein paar Tagen zwicken, funktioniert wie ein Charme –

Antwort

23

Wenn Sie nach Geschwindigkeit suchen, ist ListView Gridview viel viel schneller (und hat weniger Funktionen).

Versuchen Sie, Container-Recycling zu deaktivieren.

   <tk:DataGrid x:Name="dataGrid" 
      ItemsSource="{Binding Path=Bookings}" 
      AutoGenerateColumns="False" 
      EnableRowVirtualization="True" 
      EnableColumnVirtualization="True" 
      VirtualizingStackPanel.VirtualizationMode="Standard" 
      VirtualizingStackPanel.IsVirtualizing="True"> 
+3

Wenn Sie IsVirtualisieren vor VirtualisierungMode schreiben erhalten Sie Ausnahme (zumindest ist es in .NET 4.5) ... Sie muss die Reihenfolge ändern –

+0

Ich hatte ein ähnliches Problem, mit Ausnahme der Reihenfolge der Zeilen geändert, während ich scrollte. Ich habe die Virtualisierung nicht explizit durchgeführt. Diese Antwort hat trotzdem geholfen. –

+0

VirtualizationMode = "Standard" für den Gewinn! –

4

Wenn Sie auf Virtualisierung eingeschaltet, weil das Datagrid Ladezeit ist schrecklich, dann ist hier die Lösung:

  • Abschaltzeit Virtualisierung
  • nehmen wir an,/rufen Quelle Ihre Datagrid Artikel Bindung als " Reihen“,

    public IEnumerable<Row> Rows {get; set;} 
    
  • In der Unterkunft um Ihre "Row" Klasse IsVisible und Knebel es, wenn Sie die Daten laden möchten

der Grund, dies funktioniert (nicht, wenn UI-Thread die Bindung und laden jede Kontrolle zu lösen entscheidet), weil, wenn Sie das Netz laden, überprüft er die Bindung, die alle Reihe sind unsichtbar, so dass der UI-Thread nicht durch alle Zeilen * rotiert werden muss, um sie zu erstellen, er kann zur nächsten Aufgabe gehen. Auf der anderen Seite können Sie erkennen, wann es sinnvoll ist, diese Zeilen sichtbar zu machen, wenn die View.Visibility sichtbar ist, wenn das ViewModel die Daten von irgendwo geladen hat usw. Sie haben also die volle Kontrolle. Im Folgenden durchläuft ich meine Elementquelle (Zeilen) mithilfe einer Aufgabe (in einem Hintergrundthread), setzt jedoch Sichtbarkeit im Benutzeroberflächenthread.

private _isVisible = false; 

    /// <summary> 
    /// is false by default, for performance when loading first time. 
    /// </summary> 
    public bool IsVisible 
    { 
     get { return _isVisible; } 
     set 
     { 
      if (_isVisible == value) 
       return; 
      _isVisible = value; 
      RaisePropertyChanged(() => IsVisible); 
     } 
    } 
  • In der Ansicht, wenn Datagrid Laden ist nicht erlaubt es, indem man die Iteration der Zeilen in dem Hintergrund-Thread den UI-Thread Schwein, stellen Sie dann die Sichtbarkeit auf true. Obwohl Sie sich im Hintergrundthread befinden, löst die geänderte IsVisible-Eigenschaft die Aktualisierung aus.

    private void OnGridLoaded(object sender, RoutedEventArgs e) 
    { 
        //sample bool checks, you might not need them... 
        if (firstTimeLoad && !_isDataGridLoaded) 
        { 
         Task.Factory 
          .StartNew(() => 
          { 
           /*first time loading performance tweak*/ 
           foreach (var row in _viewModel.Rows) 
            ExeOnUi(() => { row.IsVisible = true; }); 
    
           _firstTimeLoad = false; 
          }) 
        } 
    
  • vergessen ExeOnUi Code (möglicherweise überprüfen Zugriff über etwas anderes wie whateverControl.Dispatcher.CheckAccess, ich nur verwenden Microsoft.Practices hinzuzufügen.Servicelocator):

    static void ExeOnUi (Action action) 
    { 
        var srv= ServiceLocator.Current.GetInstance<IDispatchService>(); 
        if (srv.CheckAccess()) 
         action.Invoke(); 
        else 
         srv.Invoke (action); 
    } 
    
1

Ich laufe nur in ähnliches Problem und seine aufgelöst nach UpdateSourceTrigger=PropertyChanged zur Bindung hinzuzufügen.

<DataGridTemplateColumn Header="Visible"> 
    <DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <CheckBox IsChecked="{Binding IsShown,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 
</DataGridTemplateColumn>