简体   繁体   English

WPF将项添加到绑定到observablecollection异常的datagrid

[英]WPF add item to datagrid bound to observablecollection exception

I have a simple application which shows a list of books. 我有一个简单的应用程序,显示了一个书籍列表。

BookViewModel.cs 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 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>

I can view the list of books okay, I can also delete a row. 我可以查看书籍列表没关系,我也可以删除一行。

But when I try to add a new item in Datagrid, an exception occured : 但是当我尝试在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.

Should I attach an event handler when the datagrid row added? 添加数据网格行时是否应附加事件处理程序?

I thought with two way binding, any changes in each sides will be reflected to the other side? 我想用双向绑定,每边的任何变化都会反映到另一边?

Remove the MessageBox.Show() call from the CollectionChanged event. 从CollectionChanged事件中删除MessageBox.Show()调用。

Actually, remove the CollectionChanged event handler alltogether. 实际上,完全删除CollectionChanged事件处理程序。

MessageBox.Show() forces the Dispatcher to flush, and doing so while a CollectionChanged event is raised is not a good idea. MessageBox.Show()强制Dispatcher刷新,并且在引发CollectionChanged事件时这样做不是一个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 访问绑定到 WPF DataGrid 的 ObservableCollection 中的项目 - Accessing items in ObservableCollection bound to WPF DataGrid 访问ObservableCollection中的项目绑定到WPF DataGrid - Accesing items in ObservableCollection bound to WPF DataGrid DataGrid未绑定到ObservableCollection - DataGrid is not bound to the ObservableCollection 问:C#WPF数据网格绑定到ObservableCollection <T> 没有更新 - Q: C# WPF DataGrid bound to ObservableCollection<T> gets not updated WPF:在重新实例化绑定的ObservableCollection时,DataGrid上的水平ScrollViewer捕捉到右侧 - WPF: Horizontal ScrollViewer on DataGrid snapping to right side on reinstantation of the bound ObservableCollection 为什么 DataGrid 项目即使绑定到在 WPF 中有行的 ObservableCollection 也是空的? - Why are DataGrid items empty even if it is bound to an ObservableCollection that has rows in WPF? WPF-当我从其他窗口添加项目时,Observablecollection绑定的DataGrid无法更新 - WPF - Observablecollection binded DataGrid not updating when i add item from other window 将项目添加到绑定的ObservableCollection时未调用WPF Polyline的转换器 - WPF Polyline's converter not invoked when item added to bound ObservableCollection Datagrid绑定到ObservableCollection WPF - Datagrid Binding to ObservableCollection WPF WPF DataGrid CanUserAddRows到ObservableCollection - WPF DataGrid CanUserAddRows into ObservableCollection
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM