应用 TreeView 过滤器后 DataGridView 中出现多余的行
Posted
技术标签:
【中文标题】应用 TreeView 过滤器后 DataGridView 中出现多余的行【英文标题】:Excess rows appear in DataGridView after apply TreeView Filter 【发布时间】:2020-02-18 05:17:40 【问题描述】:应用过滤器后显示行出现问题。在 DataGridView 我使用动态更新。
问题描述:
应用过滤器后(通过条件Rows.Visible = true
或Rows.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 中出现多余的行的主要内容,如果未能解决你的问题,请参考以下文章
QTreeWidget控件中 itemchanged信号触发后,怎么获取item修改前的值
使用 TextBox 和 DatePicker 元素过滤 WPF DataGrid 行