2012-11-14 74 views
3

我想在DataGrid中顯示文件的內容。 (該文件包含超過200,000行)DataGrid通過滾動拋出InvalidOperationException

使用數據顯示網格很快。

但是當我使用滾動條(用於上下滾動),我有以下異常:

System.InvalidOperationException: 
{"An ItemsControl is inconsistent with its items source.\n See the inner exception for more information."} 

的InnerException:

Information for developers (use Text Visualizer to read this): 
This exception was thrown because the generator for control 'System.Windows.Controls.DataGrid Items.Count:0' with name '(unnamed)' has received sequence of CollectionChanged events that do not agree with the current state of the Items collection. The following differences were detected: 
    Accumulated count 0 is different from actual count 200000. [Accumulated count is (Count at last Reset + #Adds - #Removes since last Reset).] 

One or more of the following sources may have raised the wrong events: 
    System.Windows.Controls.ItemContainerGenerator 
     System.Windows.Controls.ItemCollection 
     System.Windows.Data.ListCollectionView 
     System.Collections.Generic.List`1[[WpfApplication3.Entry, WpfApplication3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] 
(The starred sources are considered more likely to be the cause of the problem.) 

The most common causes are (a) changing the collection or its Count without raising a corresponding event, and (b) raising an event with an incorrect index or item parameter. 

The exception's stack trace describes how the inconsistencies were detected, not how they occurred. To get a more timely exception, set the attached property 'PresentationTraceSources.TraceLevel' on the generator to value 'High' and rerun the scenario. One way to do this is to run a command similar to the following: 
    System.Diagnostics.PresentationTraceSources.SetTraceLevel(myItemsControl.ItemContainerGenerator, System.Diagnostics.PresentationTraceLevel.High) 
from the Immediate window. This causes the detection logic to run after every CollectionChanged event, so it will slow down the application. 

的異常告訴它:「已經收到的序列CollectionChanged事件與Items集合的當前狀態不一致。「

那的代碼:

MainWindow.xaml

<Window x:Class="WpfApplication3.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WpfApplication3="clr-namespace:WpfApplication3" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid Name="Test"> 
     <WpfApplication3:Viewer x:Name="LogUC" /> 
    </Grid> 
</Window> 

MainWindow.xaml.cs

public partial class MainWindow 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     Test.DataContext = this; 

     LogUC.Loaded += LogUcOnLoaded; 
    } 

    private void LogUcOnLoaded(object sender, RoutedEventArgs routedEventArgs) 
    { 
     LogUC.Test(); 
    } 
} 

Viewer.xaml

<UserControl x:Class="WpfApplication3.Viewer" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Height="300" Width="300"> 
    <Grid Name="Container"> 
     <DataGrid ItemsSource="{Binding Path=EntryCollection, Mode=OneTime}" 
        AutoGenerateColumns="False" 
        CanUserResizeColumns="True" 
        CanUserResizeRows="True" 
        CanUserAddRows="False" 
        CanUserDeleteRows="False" 
        IsReadOnly="True"> 
      <DataGrid.Columns> 
       <DataGridTextColumn Binding="{Binding ErrorCode}" Header="" /> 
       <DataGridTextColumn Binding="{Binding Time}" Header="Time" /> 
       <DataGridTextColumn Binding="{Binding Content}" Header="Content" /> 
      </DataGrid.Columns> 
     </DataGrid> 
    </Grid> 
</UserControl> 

Viewer.xaml.cs

public partial class Viewer : INotifyPropertyChanged 
{ 
    public Viewer() 
    { 
     EntryCollection = new List<Entry>(); 
     InitializeComponent(); 
     Container.DataContext = this; 
    } 

    public List<Entry> EntryCollection { get; set; } 

    internal void Test() 
    { 
     List<Entry> test = new List<Entry>(); 

     for (int i = 0; i < 200000; i++) 
     { 
      Entry entry = new Entry(){ 
       ErrorCode = 0, 
       Time = DateTime.Now.ToString(), 
       Content = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." 
      }; 
      test.Add(entry); 
     } 

     EntryCollection.AddRange(test); 
     OnPropertyChanged("EntryCollection"); 
    } 

    #region Implementation of INotifyPropertyChanged 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    #endregion Implementation of INotifyPropertyChanged 
} 

Entry.cs

public class Entry 
{ 
    public int ErrorCode { get; set; } 

    public string Time { get; set; } 

    public string Content { get; set; } 
} 

什麼問題?

回答

6

我不確定爲什麼發生這種情況,但我可以告訴你如何使它工作。

它看起來像你永遠不會告訴DataGrid EntryCollection中的項目已經改變,通過引發適當的事件。

OnPropertyChanged("EntryCollection")給你打電話Test方法有沒有效果,因爲你有Mode=OneTime在DataGrid上綁定,因爲EntryCollection對象是List而不是ObservableCollection,項目它的加入不會引起任何事件通知DataGrid。

我看到它的方式,你可以做兩件事來解決這個問題。

  1. EntryCollectionObservableCollection從而添加項/刪除DataGrid的通知。然後您可以刪除OnPropertyChanged電話,並仍然有Mode=OneTime

    public Viewer() 
    { 
        EntryCollection = new ObservableCollection<Entry>(); 
        InitializeComponent(); 
        Container.DataContext = this; 
    } 
    
    public ObservableCollection<Entry> EntryCollection { get; set; } 
    
    internal void Test() 
    { 
        for (int i = 0; i < 200000; i++) 
        { 
         Entry entry = new Entry() 
         { 
          ErrorCode = 0, 
          Time = DateTime.Now.ToString(), 
          Content = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." 
         }; 
    
         EntryCollection.Add(entry); 
        } 
    } 
    
  2. 而不是增加項目EntryCollection的,將其設置爲一個新的實例,提高PropertyChanged事件。這樣做,您需要刪除XAML中的Mode=OneTime設置。

    public Viewer() 
    { 
        EntryCollection = new List<Entry>();  
        InitializeComponent(); 
        Container.DataContext = this; 
    } 
    
    public List<Entry> EntryCollection { get; set; } 
    
    internal void Test() 
    { 
        List<Entry> test = new List<Entry>(); 
    
        for (int i = 0; i < 200000; i++) 
        { 
         Entry entry = new Entry() 
         { 
          ErrorCode = 0, 
          Time = DateTime.Now.ToString(), 
          Content = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." 
         }; 
         test.Add(entry);  
        } 
    
        EntryCollection = test; 
        OnPropertyChanged("EntryCollection"); 
    } 
    
相關問題