前回でひとまず並べ替えができたので、検索機能(フィルタ機能)をつけてみます。
codeprojectのサンプルだと、フィールド毎のフィルタリングをしているようですが、こういう検索ってあんまり使わないんですよねー。検索ボックスひとつで主要なフィールドを検索してくれたほうが都合が良い事が多い気がします。
今回は、検索ボックスひとつだけパターンで実装します。(けっしてめんどくさいわけではありません)
controller
検索とか言っても、要はLINQのWhere句を足すだけなので、
ロジックはcontrollerをちょっと変更するだけです。
(ほんとはレポジトリクラスとかでやるのかな)
1
2
3
4
5
6
7
8
|
public ActionResult Index(string sort,string filter) //filter追加
{
var query = db.Articles.AsQueryable(); //データソース
// filterロジック
if(!string.IsNullOrEmpty(filter)) {
query = query.Where(a => a.Title.Contains(filter) || a.Description.Contains(filter));
}
...
|
actionの引数にfilterを追加して、データソースとなるクエリにwhereを足してます。
検索対象はTitleとDeacription.
Viewには検索用のフォームを追加します。
1
2
3
4
5
|
@using (Html.BeginForm(new { sort = SortDef.SortKey })) {
@Html.TextBox("filter","test")
<input type="submit" value="search" />
}
|
動かすとかんな感じです。
Sortとfilterパラメータの保持
一見いけているように見えますが、ソートすると検索フィルタがクリアされてしまいます。
ソート用のActionLinkにフィルター情報が無いからですね。
ひとまずViewBagでフィルター情報をViewに渡すようにします。
controller
1
2
3
4
|
ViewBag.SortDef = sort_def; //リンク作成用にソート定義を渡す
ViewBag.InputedFilter = filter; //入力されたフィルター ←追加
return View(query.ToList()); //ソート済み結果をViewに返す。
}
|
View
ViewではViewBagの内容をStringに詰め替えて各ソートリンクのrouteValueにセットします。
1
2
3
4
5
6
7
8
9
10
11
|
@{
ViewBag.Title = "Index";
SortDefinition<Article> SortDef = ViewBag.SortDef; //型付け
string InputedFilter = ViewBag.InputedFilter; //ユーザー入力フィルタ ←追加
}
...
...
@Html.ActionLink(
Html.DisplayNameFor(model => model.Url).ToString(),
"Index", new { sort = SortDef.GetNextSortKey(model => model.Url) , filter = InputedFilter})
|
一応、意図した動きをしているようですが、なんか書き方が冗長な気がします。
後でもう少し簡潔に書けるように変更するかも。
その前に、やる気が出たらページングを追加します。