【问题标题】:A Collection *OF* DataGridViews? Manipulating all DataGridViews at Once一个集合 *OF* DataGridViews?一次操作所有 DataGridView
【发布时间】:2013-07-02 02:12:19
【问题描述】:

我正在继续研究一些 VSTO,我想知道是否有一种方法可以同时引用一个类中的所有数据网格视图。我似乎无法弄清楚容器应该是什么,我似乎无法将它们添加到数组/其他容器中?

我想要做的伪代码类似于:

For Each datagridview in Globals.MyUserControl
   'change some datagridview property ie:
   datagridview1.ReadOnly = True
Next

我会很高兴在 C# 或 VB.net 中,或者真的任何解释这是否可以完成。目前我正在为所有不同的 datagridviews 手动设置它,随着这个数字的增长,我想要一种方法来一次全部点击它们。

仍在尝试解决以下解决方案,我尝试过的另一种方法不起作用:

    For Each ctl In Me.Controls
        If TypeOf ctl Is DataGridView Then
            ctl.ReadOnly = True
            ctl.AllowUserToDeleteRows = False
        End If
    Next

但我不知道为什么这不起作用。

【问题讨论】:

    标签: c# vb.net datagridview


    【解决方案1】:

    您可以使用 foreach 循环:

    foreach (DataGridView ctrl in Globals.MyUserControl.Controls)
        ctrl.ReadOnly = true;
    

    如果您希望控件集合中有任何您不想设置为只读的非 datagridview 控件,那么您可以检查 ctrl 的类型,而不是单个语句。

    foreach (Control ctrl in Globals.MyUserControl.Controls)
        if(ctrl is DataGridView) ctrl.ReadOnly = true;
    

    使用 LINQ,您可以这样做:

    Globals.MyUserControl.Controls.Cast<Control>().ToList().ForEach((ctrl) => { if (ctrl is DataGridView) ((DataGridView)ctrl).ReadOnly = true; });
    

    或者,如果您的所有控件都已知是 DataGridView 控件,那么您可以这样做:

    Globals.MyUserControl.Controls.Cast<DataGridView>().ToList().ForEach(ctrl => ctrl.ReadOnly = true);
    

    要在其他控件中查找子控件,请定义一个递归方法并调用它:

        private static void FindControlsRecursively(Control.ControlCollection collection)
        {
            foreach (Control ctrl in collection)
            {
                if (ctrl is DataGridView)
                    ((Label)ctrl).ReadOnly = true;
                else if (ctrl.Controls.Count > 0)
                    FindControlsRecursively(ctrl.Controls);
            }
        }
    

    然后从您的用户控件中使用您的用户控件的控件调用它:

    FindControlsRecursively(this.Controls);
    

    【讨论】:

    • 我很难访问我的 UserControl 的 ToList 或任何 Windows 窗体?当我制作一个任意列表时,我得到了。我似乎也无法将 datagridviews 添加到列表中?
    • 对不起,应该是 MyUserControl.Controls。稍后编辑代码。
    • 用户窗体和用户控件似乎没有控件的参考/定义。有 ControlCollection 但不包含 ToList?
    • 啊,我的错。我总是忘记框架中的某些集合没有 ForEach 扩展。改为使用简单的 foreach 循环进行更新。 :(
    • 如果 Globals.MyUserControl 集合实现 IEnumerable 而不是 IEnumerable 那么您只需要调用 .Cast 其中 T 是在使用 linq 之前覆盖数组中所有类型的最窄类型将其转换为 IEnumerable.
    【解决方案2】:

    这样的事情应该可以工作:

        For Each ctl In Me.Controls.OfType(Of DataGridView)()
            ctl.ReadOnly = True
            ctl.AllowUserToDeleteRows = False
        Next
    

    或 C#

            foreach (DataGridView ctrl in this.Controls.OfType<DataGridView>())
            {
                ctrl.ReadOnly = true;
                ctrl.AllowUserToDeleteRows = false;
            }
    

    这只会循环表单中的 DataGridView。

    如果需要,您还可以将它们添加到 List(Of DataGridView) 中

    另一种选择是声明一个继承 DataGridView 的类,设置您想要的属性,并声明此类型的新数据网格视图以添加到您的表单中。

    【讨论】:

    • 这会编译,但实际上并没有做任何事情。如果你添加MsgBox(ctl.Name),你会注意到什么都没有出现,所以我猜即使我把它放在用户控件中,添加 Me.Controls 也不会得到数据网格视图(似乎得到标签控件等)
    • 那么 DatGridView 的形式不是您调用它的形式。声明一个类级别列表,然后在每个表单构造函数中将任何 DGV 添加到列表中。现在,您应该可以从任何形式设置它们的属性。在 C# 中,您可能必须首先将每个 DGV 的修饰符更改为 public。
    • 是的,它们都嵌套在一个选项卡控件中,该控件采用我调用的形式。抱歉,认为它是递归的。
    • 将 Me 或 this 更改为 tabcontrol 的名称。如有必要,您可能还必须遍历每个标签页。
    【解决方案3】:

    我不确定是否应该将其放入答案中,或者 Tombola 是否想将其移至他的答案中,但这是我的解决方案。问题是我所有的数据网格视图都嵌套在选项卡控件的选项卡页上。为了让它工作,我使用了:

        For Each tabpg In TabControl1.TabPages()
            For Each ctl In tabpg.Controls  'note, was not able to use 'OfType here, but had to drop to the If statement or I ran into runtime errors.
                If TypeOf ctl Is DataGridView Then
                    ctl.ReadOnly = True
                    ctl.AllowUserToDeleteRows = False
                End If
            Next
        Next
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-19
      • 2012-09-25
      • 2015-10-14
      • 1970-01-01
      • 2020-05-17
      • 2011-07-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多