我有一个显示书籍清单的简单应用程序。
BookViewModel.cs
public class BookViewModel : INotifyPropertyChanged
{
private readonly IBookRepository _bookRepository;
private bool _isDirty = false;
public ICommand UpdateCommand { get; set; }
public bool IsDirty { get { return _isDirty; } }
public BookViewModel(IBookRepository bookRepository)
{
_bookRepository = bookRepository;
UpdateCommand = new UpdateAction(this);
var books = _bookRepository.GetAll();
_allBooks = new ObservableCollection<BookModel>();
_allBooks.CollectionChanged += collectionChanged;
foreach (var book in books)
{
_allBooks.Add(new BookModel()
{
Title = book.Title,
Stock = book.Stock
});
}
}
private ObservableCollection<BookModel> _allBooks;
private BookModel _book;
public BookModel Book
{
get { return _book; }
set
{
_book = value;
OnPropertyChanged("Book");
}
}
public ObservableCollection<BookModel> AllBooks
{
get
{
return _allBooks;
}
set
{
_allBooks = value;
}
}
void collectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
System.Windows.MessageBox.Show(e.Action.ToString());
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
_isDirty = true;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
AllBookView.xaml
<Window x:Class="LibraryManagement.Presentation.WPF.Book.Views.AllBookView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AllBookView" Height="311" Width="521">
<Grid>
<DataGrid ItemsSource="{Binding AllBooks, Mode=TwoWay}" AutoGenerateColumns="true" Height="200" HorizontalAlignment="Left" Margin="0,72,0,0" VerticalAlignment="Top" Width="499" />
<Button Command="{Binding UpdateCommand}" Content="Update" Height="23" HorizontalAlignment="Left" Margin="412,43,0,0" VerticalAlignment="Top" Width="75" />
</Grid>
</Window>
我可以查看好的书籍列表,我也可以删除一行。
但是当我尝试在Datagrid中添加一个新项时,发生了一个异常:
System.InvalidOperationException was unhandled
HResult=-2146233079
Message=An ItemsControl is inconsistent with its items source.
See the inner exception for more information.
Source=PresentationFramework
StackTrace:
at System.Windows.Controls.ItemContainerGenerator.Verify()
at System.Windows.Controls.VirtualizingStackPanel.MeasureChild(IItemContainerGenerator& generator, IContainItemStorage& itemStorageProvider, Object& parentItem, Boolean& hasUniformOrAverageContainerSizeBeenSet, Double& computedUniformOrAverageContainerSize, Boolean& computedAreContainersUniformlySized, IList& items, Object& item, IList& children, Int32& childIndex, Boolean& visualOrderChanged, Boolean& isHorizontal, Size& childConstraint, Rect& viewport, VirtualizationCacheLength& cacheSize, VirtualizationCacheLengthUnit& cacheUnit, Boolean& foundFirstItemInViewport, Double& firstItemInViewportOffset, Size& stackPixelSize, Size& stackPixelSizeInViewport, Size& stackPixelSizeInCacheBeforeViewport, Size& stackPixelSizeInCacheAfterViewport, Size& stackLogicalSize, Size& stackLogicalSizeInViewport, Size& stackLogicalSizeInCacheBeforeViewport, Size& stackLogicalSizeInCacheAfterViewport, Boolean& mustDisableVirtualization, Boolean isBeforeFirstItem, Boolean isAfterFirstItem, Boolean isAfterLastItem, Boolean
...
InnerException:
HResult=-2146233088
Message=Information for developers (use Text Visualizer to read this):
This exception was thrown because the generator for control 'System.Windows.Controls.DataGrid Items.Count:3' 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 2 is different from actual count 3. [Accumulated count is (Count at last Reset + #Adds - #Removes since last Reset).]
At index 1: Generator's item '{NewItemPlaceholder}' is different from actual item 'LibraryManagement.Presentation.WPF.Book.BookModel'.
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.ObjectModel.ObservableCollection`1[[LibraryManagement.Presentation.WPF.Book.BookModel, LibraryManagement.Presentation.WPF, 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.
我应该在添加数据网格行时附加事件处理程序吗?
我认为双向绑定,双方的任何变化都会反映到另一方?
答案 0 :(得分:6)
从CollectionChanged事件中删除MessageBox.Show()
调用。
实际上,完全删除CollectionChanged事件处理程序。
MessageBox.Show()
强制Dispatcher刷新,并且在引发CollectionChanged事件时这样做不是一个好主意。