无法将DataGridView中的行设置为不可见

32

我有一个 DataGridView,我设置了它的 DataSource

taskerEntities te = new taskerEntities();
var OMsMasterDescriptiveIndicators = te.MyTable.Select(x => new lccls {Id = x.Id, name = x.name }).ToList();
MyGrid.DataSource = OMsMasterDescriptiveIndicators;

使用我的lccls类作为

public class lccls
    {
        public string Id { get; set; }
        public Nullable<decimal> name { get; set; }
    }

在某个事件中,我希望将当前行设置为不可见:

 MyGrid.Rows[5].Visible = false;

但我无法做到这一点。相反,抛出了以下错误信息的异常:

  

无法使与货币管理器位置相关联的行不可见

我怀疑原因与设置 DataSource 有关,但是为什么呢?


你会把代码 MyGrid.Rows[e.RowIndex].Visible = false; 放在哪里?奇怪的是,如果你使用任意的 index,比如 01 等,它可以成功隐藏行。 - King King
我已经改变了 e.rowindex,但它仍然不起作用。 - Amit Bisht
你是否在运行时更改数据源(删除行)? - varocarbas
我并不是在删除该行,而是在隐藏该行。 - Amit Bisht
1
是的,我明白了。我的意思是,如果您在运行时更改数据源,例如:启动数据源1、2、3;然后删除记录2;那么您打算使DGV中给定的行不可见。我已经阅读了您的答案,很可能这就是问题所在。最安全的方法是直接从DGV执行任何更新(或者,在从数据源执行更新时,确保您考虑到DGV中涉及的不同索引的变化)。 - varocarbas
8个回答

71

我搜索了很多,找到了 解决方法

CurrencyManager currencyManager1 = (CurrencyManager)BindingContext[MyGrid.DataSource];  
currencyManager1.SuspendBinding();
MyGrid.Rows[5].Visible = false;
currencyManager1.ResumeBinding();

9
非常感谢。我仍然震惊于为什么隐藏行如此复杂?!?! - Lev Z
5
为了使其正常工作,我不得不将 CurrencyManager currencyManager1 = (CurrencyManager)BindingContext[MyGrid.DataSource]; 更改为 CurrencyManager currencyManager1 = (CurrencyManager)MyGrid.BindingContext[MyGrid.DataSource];。请注意,这两个代码片段的含义是相同的。 - Shashank Shekhar
是的,它确实有效。我认为我知道为什么会遇到这个问题,因为我正在使用多线程来填充列表,而这个列表是我的网格数据源。我猜测的原因是,在我开始尝试隐藏行时,并不是所有的线程都已经完成。 - Shanerk
8
@Lev: 我仍然震惊于为什么隐藏行如此复杂 ?!?!? 其实不是,只需将 CurrentCell = null 即可。 - TaW

17

当试图隐藏当前单元格时,无法将您的DataGridView行可见性属性设置为false,会遇到这样的错误。

解决方案:

当您的DataGridView数据源不为空时:

  CurrencyManager currencyManager1 = (CurrencyManager)BindingContext[yourDataGridView.DataSource];
                       currencyManager1.SuspendBinding();
                       yourDataGridView.Rows[Target Index].Visible = false;
                       currencyManager1.ResumeBinding();

当你的DataGridView数据源为null时:

 yourDataGridView.CurrentCell = null;
 yourDataGridView.Rows[Target Index].Visible = false;

4
+1 是因为你的第二个解决方案对我有用。尽管我绑定了一个 DataSet,而且 DataSource 不为空,但第一个解决方案 并没有 起作用!想想看... - JonP

2

我有一个例子给你。我有一个数据网格视图,可能会选择多行。当我点击按钮时,将不可见选择的行。试试这个:

foreach (DataGridViewRow row in dataGridView1.SelectedRows)
        {
            CurrencyManager currencyManager1 =(CurrencyManager)BindingContext[dataGridView1.DataSource];
                currencyManager1.SuspendBinding();
                dataGridView1.CurrentCell = null;
                row.Visible = false;
        }
        dataGridView1.Refresh();

请记得设置属性 SelectionMode: FullRowSelect


您忘记恢复CurrencyManager绑定了。此外,您只需要一次暂停CurrencyManager。您应该在更新循环之外暂停CurrencyManager,并在循环后恢复它。您也不需要将CurrentCell设置为null,在循环中不应这样做。您不需要调用Refresh() - DataGridView会自行处理屏幕更新。 - MadManMarkAu
1
我的问题通过在 row.Visible = false; 之前添加 dataGridView1.CurrentCell = null; 来解决。不需要使用 SuspendBinding - PKanold

2

示例

        foreach (DataGridViewRow rw in dataGridView1.Rows)
        {

        if (rw.Cells[14].Value.ToString() == "") // this Cell have a TEXT, 
            {
                CurrencyManager currencyManager1 = (CurrencyManager)BindingContext[dataGridView1.DataSource];
                currencyManager1.SuspendBinding();
                rw.Visible = false; 
                currencyManager1.ResumeBinding();

            }
        }

仅显示包含单元格索引14的行,如果此单元格为空或空白,则整个行不显示。


0

0
我尝试在CellFormating事件中隐藏一行,但它没有起作用。看起来货币管理器无法暂停引发事件的行,因此我需要先处理该行(第0行处理最后一行)。
Private Sub DgView1_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles DgView1.CellFormatting
        If DgView1.Rows(e.RowIndex).Cells(e.ColumnIndex).OwningColumn.Name = CoID Then
            Dim k = If(e.RowIndex = 0, DgView1.RowCount - 1, e.RowIndex - 1)
            DgView1.Rows(k).Visible = Countries.Rows(k)("Ro")
        End If
End Sub

0

我知道这是一个老话题,但有一个替代方案(我的代码是vb.net,但我认为它可以翻译)

If WO_DGV.CurrentCell.RowIndex = i Then
  'you cannot make invisible the row that is 'current'
  WO_DGV.CurrentCell = WO_DGV.Rows(i - 1).Cells("act") 
  'to get to this code I know that there is a row before i, which is why I can use i-1 as new focus
End If
WO_DGV.Rows(i).Visible = False 

0

也许这已经过时了,但是:

这里有一个简单的方法:

var item = dgv.Rows.Cast<DataGridViewRow>().FirstOrDefault(c => c.Cells[x].Value?.ToString() == X);
            if (item != null)
            {
                availableIpsDataGridView.CurrentCell = null;
                item.Visible = false;
            }

并通过以下方式使其可见:

var item = dgv.Rows.Cast<DataGridViewRow>().FirstOrDefault(c => c.Cells[x].Value?.ToString() == X);
                if (item != null)
                {
                    item.Visible = true;
                }

目前你的答案写得不够清晰,请编辑以添加更多细节,帮助其他人理解它如何回答所问的问题。你可以在帮助中心找到有关编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接