簡體   English   中英

如何以編程方式隱藏WPF DataGrid行

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM