Here is a subclass of DataGrid with MaxRows Dependency. It should be noted that in case the DataGrid is in edit mode and CanUserAddRows InvalidOperationException (as you mentioned in the question).
InvalidOperationException
"NewItemPlaceholderPosition" is not allowed during a transaction started by 'AddNew'.
To get around this, the IsInEditMode method in IsInEditMode is OnItemsChanged , and if it returns true, we subscribe to the LayoutUpdated event to check IsInEditMode again.
In addition, if MaxRows set to 20, it should allow 20 lines if CanUserAddRows is True and 19 lines False (to place NewItemPlaceHolder , which is not in False).
It can be used as
<local:MaxRowsDataGrid MaxRows="20" CanUserAddRows="True" ...>
MaxRowsDataGrid
public class MaxRowsDataGrid : DataGrid { public static readonly DependencyProperty MaxRowsProperty = DependencyProperty.Register("MaxRows", typeof(int), typeof(MaxRowsDataGrid), new UIPropertyMetadata(0, MaxRowsPropertyChanged)); private static void MaxRowsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) { MaxRowsDataGrid maxRowsDataGrid = source as MaxRowsDataGrid; maxRowsDataGrid.SetCanUserAddRowsState(); } public int MaxRows { get { return (int)GetValue(MaxRowsProperty); } set { SetValue(MaxRowsProperty, value); } } private bool m_changingState; public MaxRowsDataGrid() { m_changingState = false; } protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { base.OnItemsChanged(e); if (IsInEditMode() == true) { EventHandler eventHandler = null; eventHandler += new EventHandler(delegate { if (IsInEditMode() == false) { SetCanUserAddRowsState(); LayoutUpdated -= eventHandler; } }); LayoutUpdated += eventHandler; } else { SetCanUserAddRowsState(); } } private bool IsInEditMode() { IEditableCollectionView itemsView = Items; if (itemsView.IsAddingNew == false && itemsView.IsEditingItem == false) { return false; } return true; }
source share