簡體   English   中英

WPF將項添加到綁定到observablecollection異常的datagrid

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

我有一個簡單的應用程序,顯示了一個書籍列表。

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.

添加數據網格行時是否應附加事件處理程序?

我想用雙向綁定,每邊的任何變化都會反映到另一邊?

從CollectionChanged事件中刪除MessageBox.Show()調用。

實際上,完全刪除CollectionChanged事件處理程序。

MessageBox.Show()強制Dispatcher刷新,並且在引發CollectionChanged事件時這樣做不是一個好主意。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM