[英]How to hide WPF DataGrid rows programmatically
我有大约2500个条目的DataGrid。 我希望用户能够进行搜索,并且隐藏不包含搜索词的行。
这是我的伪代码策略,我是C#、. Net和WPF的新手,因此可以随意推荐其他方法。
for each Row in DataGrid
for each Column in Row
if Cell doesn't contains SearchQuery
hide Row
break
在C#中:
List<int> rowsWithoutMatch = new List<int>();
for (int i = 0; i < dataGrid.Items.Count; i++)
{
DataGridRow row = (DataGridRow)dataGrid.
ItemContainerGenerator.ContainerFromIndex(i);
if (row != null)
{
for (int j = 0; j < dataGrid.Columns.Count; j++)
{
DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(row);
if (presenter != null)
{
DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(j);
if (cell != null)
{
TextBlock tb = cell.Content as TextBlock;
string content = tb.Text;
if (!(content).Contains(columnFilters[j]))
{
row.Visibility = Visibility.Collapsed;
break;
}
}
}
}
}
}
我收到了一个奇怪的错误,其中row != null
仅在前24次迭代中为null,之后均为null,因此它停止了对行的迭代。
我从这个 SO问题得知,这是因为在DataGrid中仅可见24行,而屏幕上未显示的行全部为空。
我通过将标签VirtualizingStackPanel.IsVirtualizing="False"
放入DataGrid XMAL中解决了该问题,但是现在它一次加载所有行,并且运行非常缓慢。 与添加dataGrid.UpdateLayout(); dataGrid.ScrollIntoView(dataGrid.Items[i]);
相同dataGrid.UpdateLayout(); dataGrid.ScrollIntoView(dataGrid.Items[i]);
dataGrid.UpdateLayout(); dataGrid.ScrollIntoView(dataGrid.Items[i]);
,但是还有更多错误。
我也尝试过这个,速度更快
dataGrid.DataContext = dt.AsDataView();
for (int i = dt.Rows.Count - 1; i >= 0; i--)
{
DataRow dr = dt.Rows[i];
for (int j = 0; j < columnFilters.Length; j++)
{
if (! dr[j].ToString().Contains( columnFilters[j] ))
{
dr.Delete();
break ;
}
}
}
dataGrid.DataContext = dt.AsDataView();
但是我有一个连接到DataGrid的SQL数据库,删除行成为一个巨大的问题。 另外,切换可见性似乎比弄乱DataTable更好。
我怎样才能使速度更快? 甚至,什么是我尝试做的完全不同/更好的方法? Windows窗体似乎有更多此类选项,但是现在从WPF恢复回来为时已晚。
非常感谢。
这里是一个简单的非优化的数据表到对象,可以简单地查询Linq
public class LinqTable
{
public LinqTable()
{
}
public LinqTable(DataTable sourceTable)
{
LoadFromTable(sourceTable);
}
public List<LinqRow> Rows = new List<LinqRow>();
public List<string> Columns
{
get
{
var columns = new List<string>();
if (Rows != null && Rows.Count > 0)
{
Rows[0].Fields.ForEach(field => columns.Add(field.Name));
}
return columns;
}
}
public void LoadFromTable(DataTable sourceTable)
{
sourceTable.Rows.Cast<DataRow>().ToList().ForEach(row => Rows.Add(new LinqRow(row)));
}
public DataTable AsDataTable()
{
var dt = new DataTable("data");
if (Rows != null && Rows.Count > 0)
{
Rows[0].Fields.ForEach(field =>
{
dt.Columns.Add(field.Name, field.DataType);
});
Rows.ForEach(row=>
{
var dr = dt.NewRow();
row.Fields.ForEach(field => dr[field.Name] = field.Value);
dt.Rows.Add(dr);
});
}
return dt;
}
}
public class LinqRow
{
public List<LinqField> Fields = new List<LinqField>();
public LinqRow()
{
}
public LinqRow(DataRow sourceRow)
{
sourceRow.Table.Columns.Cast<DataColumn>().ToList().ForEach(col => Fields.Add(new LinqField(col.ColumnName, sourceRow[col], col.DataType)));
}
public object this[int index]
{
get
{
return Fields[index].Value;
}
}
public object this[string name]
{
get
{
return Fields.Find(f => f.Name == name).Value;
}
}
public DataTable AsSingleRowDataTable()
{
var dt = new DataTable("data");
if (Fields != null && Fields.Count > 0)
{
Fields.ForEach(field =>
{
dt.Columns.Add(field.Name, field.DataType);
});
var dr = dt.NewRow();
Fields.ForEach(field => dr[field.Name] = field.Value);
dt.Rows.Add(dr);
}
return dt;
}
}
public class LinqField
{
public Type DataType;
public object Value;
public string Name;
public LinqField(string name, object value, Type dataType)
{
DataType = dataType;
Value = value;
Name = name;
}
public LinqField(string name, object value)
{
DataType = value.GetType();
Value = value;
Name = name;
}
public override string ToString()
{
return Value.ToString();
}
}
调用非常简单并且具有约束力。
// this create a lighter object for linq.
var myTable = new LinqTable(myDatatable);
// want to see only active clients
var filteredResult = myTable.Rows.Where(field => Convert.ToBoolean(field["IsActive"].ToString()) == true).ToList();
// now i want sort by name
var filteredResult = myTable.Rows.OrderBy(field => field["Name"].ToString()).ToList();
绑定到XAML中,您可以使用整数或字符串索引器
// by int indexer
<Textbox Text="{Binding [2]}" />
// by string indexer
<Textbox Text="{Binding [Name]}" />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.