Wpf Datagrid Max Rows - PullRequest
       4

Wpf Datagrid Max Rows

5 голосов
/ 03 февраля 2011

В настоящее время я работаю с сеткой данных, где я хочу разрешить пользователю вводить до 20 строк данных, прежде чем CanUserAddRows станет ложным.

Я создал свойство зависимости для своей собственной таблицы данных (которая получена из первоначальной). Я попытался использовать событие "ItemContainerGenerator.ItemsChanged" и проверить количество строк там, и если число строк = макс. Строк, то пользователь make может добавить строку = ложь (я получаю исключение из-за того, что мне не разрешают изменять его во время «Добавить строку».

Мне было интересно, есть ли хороший способ реализации этого ...

Спасибо и С уважением, Kevin

Ответы [ 2 ]

8 голосов
/ 29 ноября 2012

Я адепт KISS Чтобы уменьшить количество строк, необходимых для выполнения работы, и сделать ее простой, используйте следующее:

    private void MyDataGrid_LoadingRow( object sender, DataGridRowEventArgs e )
    {
        // The user cannot add more rows than allowed
        IEditableCollectionView itemsView = this.myDataGrid.Items;
        if( this.myDataGrid.Items.Count == max_RowCount + 1 && itemsView.IsAddingNew == true )
        {
            // Commit the current one added by the user
            itemsView.CommitNew();

            // Once the adding transaction is commit the user cannot add an other one
            this.myDataGrid.CanUserAddRows = false;
        }
    }

Простой и компактный; 0)

7 голосов
/ 05 февраля 2011

Вот подкласс DataGrid со MaxRows свойством зависимости. Следует отметить, что если DataGrid находится в режиме редактирования, а CanUserAddRows изменяется, то произойдет InvalidOperationException (как вы упомянули в вопросе) .

InvalidOperationException
'NewItemPlaceholderPosition' не является разрешено во время транзакции, начатой 'AddNew'.

Чтобы обойти это, метод IsInEditMode вызывается в OnItemsChanged, и если он возвращает true, мы подписываемся на событие LayoutUpdated, чтобы снова проверить IsInEditMode.

Кроме того, если для MaxRows установлено значение 20, то должно быть разрешено 20 строк, когда CanUserAddRows равно True, и 19 строк, когда False (чтобы освободить место для NewItemPlaceHolder, которого нет в False).

Может использоваться следующим образом

<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;
    }        
    // This method will raise OnItemsChanged again 
    // because a NewItemPlaceHolder will be added or removed
    // so to avoid infinite recursion a bool flag is added
    private void SetCanUserAddRowsState()
    {
        if (m_changingState == false)
        {
            m_changingState = true;
            int maxRows = (CanUserAddRows == true) ? MaxRows : MaxRows-1;
            if (Items.Count > maxRows)
            {
                CanUserAddRows = false;
            }
            else
            {
                CanUserAddRows = true;
            }
            m_changingState = false;
        }
    }
}
...