2013年2月7日 星期四

[ .NET ] 讓DataTable自己過濾資料


前陣子接到一個需求,那個情境整個讓我整個大發火:允許使用者輸入查詢條件,針對已查詢出來的結果再進行查詢

聽起來是一個很好用的功能,如果查出來的資料有30頁分頁,用這個方式來過濾資料確實是對使用者來說相當方便。
真正讓我發火的是:那個頁面是40多種查詢項目共用的,不同的查詢項目,GridView上產生的欄位會不一樣,而聽到這個需求的時候,我還在考慮是要從資料庫重新拉資料,還是只是把已經抓出來的資料藏在什麼地方,要的時候再拿出來。更重要的是,我聽到這個需求的時候,隔天就要驗收,而我還一點頭緒也沒有。
順便宣達一下:在開發功能的時候,真的要有人隨時檢視合約和工作項目之間的關聯,真的不要到驗收前才發現有一些該完成的項目沒列在工作項目裡。

--該冷靜一下的分隔線--

時程的關係,當時已經沒有時間再去改寫DAO,讓使用者在操作介面的時候讓系統重新跟資料庫不斷地拉少量資料,所以決定在頁面上動手腳。
不知道從哪時候開始就有聽說過.NET的伺服器元件裡有一個地方可以讓人寫類似SQL的過濾句,又隱約看過DataTable裡有個Select之類的東西,就打算從這方面開始著手。

查了一下又試了一下,發現有點不太容易使用。
DataTable.Select(string expression)中,Select裡可以塞一段類似SQL裡的WHERE條件句的字串,把DataTable裡的資料再做一次過濾(參考expression的寫法)。壞就壞在他回傳的是DataRow陣列,而且還是這個DataTable自己的DataRow,不是另外Create一塊新的DataRow來放,所以也不能把這些DataRow再加到其它的DataTable裡,我要怎麼顯示在介面上都不太對,這個東西就變成練習用的玩具,不算產出。

後來survey各路名門文獻來尋找靈感,就這麼無意間讓我知道由DataTable.DefaultView回傳回來的一個DataView,裡面除了裝著DataTable的資料之外,官方還說可以進行資料的篩選和排序。

是我要的篩選

於是我就在這個DataView.RowFilter裡加那些原本寫在DataTable.Select裡的expression,再把GridView和DataTable重新Bind一下,就可以得到我要的結果了!

    private void SelectDataTable(string keyword) {
        DataTable dt = (DataTable)ViewState["dtSource"];

        if (keyword == "")
        {
            dt.DefaultView.RowFilter = "";
            ViewState["RowFilter"] = "";
        }
        else
        {
            StringBuilder expWhere = new StringBuilder();
            foreach (DataColumn col in dt.Columns)
            {
                if (col.ColumnName == "SeqID") { continue; }
                if (col.DataType != typeof(string)) { continue; }
                expWhere.Append(string.Format("{0} LIKE '%{1}%' OR ", col.ColumnName, keyword));
            }
            dt.DefaultView.RowFilter = ((ViewState["RowFilter"].ToString() != "") ? ViewState["RowFilter"] + " AND " : "") + "(" + expWhere.ToString().Remove(expWhere.Length - 3, 3) + ")";
            ViewState["RowFilter"] = dt.DefaultView.RowFilter;
        }
        ViewState["dtSource"] = dt;
        SetGridView(dt);
    }



老天保佑,It's work!


下面是畫面圖。為保護當事人已馬賽克(?)處理

圖1. 查出來的資料很多,有8頁

 圖2. 透過RowFilter來過濾資料

圖3. 再濾一次。這個功能會讓關鍵字查詢用AND的方式把前後的查詢一次一次濾掉,不過這裡看不出來....


Ref: