[英]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.