Wpf 数据网格最大行数

发布于 2024-10-15 11:09:30 字数 280 浏览 1 评论 0原文

我目前正在使用数据网格,我只想允许用户在将 CanUserAddRows 设置为 false 之前输入最多 20 行数据。

我在自己的数据网格上创建了​​一个依赖属性(源自原始数据网格)。我尝试使用事件“ItemContainerGenerator.ItemsChanged”并检查其中的行数,如果行数=最大行数,则使用户可以添加行= false(我得到一个例外,即我'我不允许在“添加行”期间更改它。

我想知道是否有一个好的方法来实现这个......

谢谢和问候, 凯文

I am currently working with data grid where I only want to allow the user to enter UP TO 20 rows of data before making CanUserAddRows to false.

I made a dependency property on my own datagrid (that derives from the original one). I tried using the event "ItemContainerGenerator.ItemsChanged" and check for row count in there and if row count = max rows, then make can user add row = false (I get an exception for that saying i'm not allow to change it during "Add Row".

I was wondering if there is a good way on implementing this ....

Thanks and Regards,
Kevin

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

╰つ倒转 2024-10-22 11:09:30

这是一个具有 MaxRows 依赖属性的子类 DataGrid。关于实现需要注意的事情是,如果 DataGrid 处于编辑模式并且 CanUserAddRows 发生更改,则会发生 InvalidOperationException (就像您一样)问题中提到)。

InvalidOperationException
“NewItemPlaceholderPosition”不是
在开始的交易期间允许
“添加新的”。

为了解决这个问题,在 OnItemsChanged 中调用一个名为 IsInEditMode 的方法,如果它返回 true,我们订阅事件 LayoutUpdated 来检查 IsInEditMode再次。

此外,如果 MaxRows 设置为 20,则当 CanUserAddRows 为 True 时,必须允许 20 行,当 False 时,必须允许 19 行(为 NewItemPlaceHolder 腾出位置) code> 在 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;
        }
    }
}

Here's a subclassed DataGrid with a MaxRows Dependency Property. The things to note about the implementation is if the DataGrid is in edit mode and CanUserAddRows is changed an InvalidOperationException will occur (like you mentioned in the question).

InvalidOperationException
'NewItemPlaceholderPosition' is not
allowed during a transaction begun by
'AddNew'.

To workaround this, a method called IsInEditMode is called in OnItemsChanged and if it returns true we subscribe to the event LayoutUpdated to check IsInEditMode again.

Also, if MaxRows is set to 20, it must allow 20 rows when CanUserAddRows is True, and 19 rows when False (to make place for the NewItemPlaceHolder which isn't present on False).

It can be used like this

<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;
        }
    }
}
腻橙味 2024-10-22 11:09:30

我是 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)

I am an adept of K.I.S.S. To reduce the amount of lines required to do the job and keep it simple, use the following:

    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;
        }
    }

Simple and compact ;0)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文