应用 TreeView 过滤器后 DataGridView 中出现多余的行

Posted

技术标签:

【中文标题】应用 TreeView 过滤器后 DataGridView 中出现多余的行【英文标题】:Excess rows appear in DataGridView after apply TreeView Filter 【发布时间】:2020-02-18 05:17:40 【问题描述】:

应用过滤器后显示行出现问题。在 DataGridView 我使用动态更新。

问题描述: 应用过滤器后(通过条件Rows.Visible = trueRows.Visible = false),出现其他行,虽然不显示整个新行,但只显示其更新的单元格,如图所示:

需要注意的是,表更新不会发生在主线程中;更新以固定间隔thread_delay_time 进行。

代码TreeView1_AfterSelect:

private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e)

    Classes.TreeViewFilter treeViewFilter = new Classes.TreeViewFilter();
    treeViewFilter.Filter(this);

部分班级TreeViewFilter

class TreeViewFilter
    
        public void Filter(MainForm mainForm)
        
            switch (mainForm.TreeView1.SelectedNode.Text)
            
                case "Category":
                    mainForm.dataGridView1.CurrentCell = null;
                    for (int i = 0; i < mainForm.dataGridView1.Rows.Count; i++)
                    
                        mainForm.dataGridView1.Rows[i].Visible = true;
                    
                    break;
                case "MED":
                    mainForm.dataGridView1.CurrentCell = null;
                    for (int i = 0; i < mainForm.dataGridView1.Rows.Count; i++)
                    
                        if (Convert.ToInt32(mainForm.dataGridView1.Rows[i].Cells[13].Value) == 1)
                            mainForm.dataGridView1.Rows[i].Visible = true;
                        else
                            mainForm.dataGridView1.Rows[i].Visible = false;
                    
                    break;
                case "Air":
                    mainForm.dataGridView1.CurrentCell = null;
                    for (int i = 0; i < mainForm.dataGridView1.Rows.Count; i++)
                    
                        if (Convert.ToInt32(mainForm.dataGridView1.Rows[i].Cells[13].Value) == 2)
                            mainForm.dataGridView1.Rows[i].Visible = true;
                        
                        else
                            mainForm.dataGridView1.Rows[i].Visible = false;

...等等

不仅After_Select 方法需要过滤,还需要动态过滤(对于选定的节点TreeView,只显示所需的行集)。通过方法DataGridView1_CellValueChanged和新线程private void ThreeViewMarker()实现:

 Invoke((MethodInvoker)delegate
            
                switch (TreeView1.SelectedNode.Text)
                
                    case "Category":
                        dataGridView1.CurrentCell = null;
                        for (int i = 0; i < dataGridView1.Rows.Count; i++)
                        
                    CurrencyManager currencyManager = (CurrencyManager)BindingContext[dataGridView1.DataSource];
                    currencyManager.SuspendBinding();
                    dataGridView1.Rows[i].Visible = true;
                    currencyManager.ResumeBinding();
                        
                        break;
                    case "MED":
                        dataGridView1.CurrentCell = null;
                        for (int i = 0; i < dataGridView1.Rows.Count; i++)
                        
                            if (Convert.ToInt32(dataGridView1.Rows[i].Cells[13].Value) == 1)
                            
                        CurrencyManager currencyManager = (CurrencyManager)BindingContext[dataGridView1.DataSource];
                        currencyManager.SuspendBinding();
                        dataGridView1.Rows[i].Visible = true;
                        currencyManager.ResumeBinding();
                            
                            else
                            
                        CurrencyManager currencyManager = (CurrencyManager)BindingContext[dataGridView1.DataSource];
                        currencyManager.SuspendBinding();
                        dataGridView1.Rows[i].Visible = false;
                        currencyManager.ResumeBinding();
                            
                        
                        break;
                    case "Air":
                        dataGridView1.CurrentCell = null;
                        for (int i = 0; i < dataGridView1.Rows.Count; i++)
                        
                            if (Convert.ToInt32(dataGridView1.Rows[i].Cells[13].Value) == 2)
                            
                        CurrencyManager currencyManager = (CurrencyManager)BindingContext[dataGridView1.DataSource];
                        currencyManager.SuspendBinding();
                        dataGridView1.Rows[i].Visible = true;
                        currencyManager.ResumeBinding();
                            
                            else
                            
                        CurrencyManager currencyManager = (CurrencyManager)BindingContext[dataGridView1.DataSource];
                        currencyManager.SuspendBinding();
                        dataGridView1.Rows[i].Visible = false;
                        currencyManager.ResumeBinding();
                            
                        

...等等

与前一种方法类似,这种方法也不能正常工作。

表单整体仍有无法理解的行为,缩放窗口时出现问题(出现集合的第一行):

在.gif中,动态更新DataGridView的方法被禁用!一个简单方法After_Select的结果。

请告诉我如何处理这个问题。我没有考虑到什么?

.gif 说明:

Категория - 类别 МЭД - 等效剂量(单位为 Мощность эквивалентной дозы) Воздух - 空气 Спец。 контроль - 特殊控制

Не работает - 不工作

Уставки - 阈值

Предаварийная - 事故前 Аварийная - 事故

为了解决这个问题,我尝试使用这个:

string columnName = "type"; // or other column
string filterValue = "2";   // or other value
string rowFilter = string.Format("[0] = '1'", columnName, filterValue);
(mainForm.dataGridView1.DataSource as DataTable).DefaultView.RowFilter = rowFilter;

但在这种情况下,不再询问隐藏的行(它们似乎从 DataSource 或类似的东西中丢失)

感谢您的帮助;我为我的英语道歉... =)

【问题讨论】:

【参考方案1】:

我设法重现了这个问题。

problem.gif

额外的行是在 CurencyManager 中选择并用三角形突出显示的行。

解决方案:

在过滤方法开始时禁用 CurrencyManager

CurrencyManager currencyManager = (CurrencyManager)BindingContext [dataGridView1.DataSource];
currencyManager.SuspendBinding();

标题的三角形会消失(但在某些情况下使用 CurrentRow 和 CurrentCell 可能会不起作用)。

将行切换到应该可见的行。

dataGridView1.CurrentCell = this.dataGridView1[columnNumber, visibleRowNumber];

但这在所有行都应该隐藏的情况下不起作用。

solution.gif

【讨论】:

【参考方案2】:

试试这个。

将可见性属性添加到您的 BindingSource 并绑定 每行对可见性属性的可见性。

禁用 RaiseListChangedEvents 并在之后重新启用它们,以及 重置绑定,以便网格知道自己更新。

CurrencyManager currencyManager = (CurrencyManager) BindingContext[dataGridView1.DataSource];

currencyManager.RaiseListChangedEvents = false;

//通过在绑定源中将可见性属性设置为false来禁用所有其他行

currencyManager.RaiseListChangedEvents = true;

currencyManager.ResetBindings();

看看这个:https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.datagridview.databindingcomplete?redirectedfrom=MSDN&view=netframework-4.8

使用 DataBindingComplete 事件来禁用/启用行

【讨论】:

感谢您的回答。如何将可见性属性添加到 BindingSource 并将行可见性属性绑定到它? CurrencyManager 没有方法(RaiseListChangedEvents、ResetBindings),但是 BindingSource 有这些方法 在我深入探讨之前,您是否尝试过在 DataGrid 上刷新? 或无效? 我试过dataGridView1.Update();和 dataGridView1.Refresh();。它没有带来任何结果。

以上是关于应用 TreeView 过滤器后 DataGridView 中出现多余的行的主要内容,如果未能解决你的问题,请参考以下文章

KendoUI 过滤器 TreeView

QTreeWidget控件中 itemchanged信号触发后,怎么获取item修改前的值

使用 TextBox 和 DatePicker 元素过滤 WPF DataGrid 行

WPF treeview扩展

silverlight datagrid怎么获取筛选后的集合

DataGrid文本框过滤不起作用