2009-09-10 80 views
6

alt text http://img3.imageshack.us/img3/1488/advancedsearch.png建議在ASP.NET

建立一個動態的「高級搜索」控制我建立在ASP.NET應用程序的「高級搜索」界面。我不需要爲我寫這個東西,但我被困在關於動態控件和ViewState的特定問題上。我想知道如何解決這個問題。這裏是我的情況:

主料:

  • 一個維修組表示實體,字段和搜索API對象,它可以處理構建搜索,生成SQL,並返回結果。所有這一切都照顧好了。
  • ASP.NET 3.5

所需界面功能性:

(1)在初始頁面加載,接口獲取預先配置的搜索對象與一組SearchCriterion對象。它結合他們到一組控件

  • 一些搜索項目是簡單的,像(見上圖):

    場(的DropDownList)|運算符(DropDownList)|對於某些字段類型的值(文本框)

  • 搜索標準控制已存儲的重要信息視圖狀態,如:

    場(的DropDownList)|運算符(DropDownList)|值(DropDownList)其中「值」下拉列表由數據庫查詢填充。

  • 某些字段查找到其它實體,這導致場選擇的鏈,如:

    字段(DropDownList的)場(DropDownList的)|運算符(DropDownList)|值

(2)用戶修改由所述搜索:

  • 添加和通過點擊各個按鈕通過改變字段,操作員或值
  • 配置現有標準卸下的搜索條件。對字段或操作員的更改將要求控件通過更改可用操作符,將「值」輸入控件更改爲其他類型,或者如果選擇/取消選擇查找類型字段,從「字段」部分添加/刪除DropDownLists, 。

(3)最後,用戶點擊「搜索」查看他們的結果。

問題:

正如你可能已經知道,如果你回答這個問題,動態添加控件的頁面消失回發。我已經創建了一個UserControl來操縱控件集合,並完整地完成上面的步驟(1),您可以在附加圖像中看到它。 (很明顯,我現在不關心風格。)

但是在Postback上,控件都沒了,我的Search API對象也沒有了。如果我可以讓動態生成的控件集合在ViewState中很好地運行,我可以檢查回發控件,重建搜索對象,然後整齊地處理控件事件。

可能的解決方案

  • 我可以使搜索對象序列化並將其存儲在視圖狀態中。然後在頁面加載時,我可以抓取它並在頁面加載時重新構建控件集合。不過,我不確定這是否能夠很好地與控件引發事件以及包含數據庫數據的下拉列表的視圖狀態發生了什麼變化 - 我可以恢復它嗎?我非常不希望在每次回發時重新查詢數據庫。

  • 我可以爲這種事情開發一個自定義服務器控件(see this link)......但這對我來說是一個新話題,並且涉及一些學習,另外我不完全確定一個自定義服務器控件是否會更好地使用非固定控制集合。有人知道嗎?

  • 我在想我可以使用數據綁定控件來完成此操作 - 例如我可以將我的標準集合綁定到具有固定控件集合的中繼器(可以隱藏未使用的「值」控件,使用「字段」下拉列表的內部中繼器)。那麼所有的信息將保持在ViewState中...對嗎?

  • 任何新的想法將不勝感激。

感謝您的幫助。 b.Fandango

+0

這是一篇很棒的文章,我試圖構建幾乎完全一樣的搜索頁面。你介意分享你的初始工作的任何例子,即創建「一組代表實體,字段和搜索的可用API對象,它們處理構建搜索,生成SQL並返回結果。」如果你有任何鏈接或信息要共享,這將是非常有益的,只是擔心,如果已經有libs /框架在做這種事情,我不想重新發明輪子。謝謝,偉大的職位! – russds 2013-07-18 17:28:20

+0

russds,我在一箇中等規模的企業軟件包上工作,該軟件包有自己的元數據(實體和字段)和搜索實現。我無法與您分享我的僱主的任何源代碼,儘管我確信他們不會介意我是否寫過關於系統該部分的設計和實施。不過,我認爲有很多「業務對象」基類庫,可以爲您提供這些類型的功能。我會看看我能爲你找到什麼,但我也建議你一邊快速的谷歌。 – 2013-07-18 20:48:53

+0

謝謝巴里。我做了一些谷歌搜索,但不完全是谷歌,我嘗試過諸如「動態搜索UI」和「asp.net高級搜索」之類的東西,但沒有具體的結果。你的描述正是我正在尋找的內容,我會搜索什麼樣的術語?謝謝! – russds 2013-07-25 20:18:39

回答

4

我一直在爲大約一天的編碼工作,並且使用我在我的問題中提出的第三個選項 - 老派數據綁定控件,使得這個工作非常漂亮。實際上,當我被迫詳細寫出問題時,我只想到了這個想法 - 這不是一直髮生在你身上嗎?

我把我的SearchCriterionControl放入一個asp:Repeater並將其綁定到我的對象集合。對於字段選擇器,我將一個asp:DropDownList放入一個嵌套的asp:Repeater中,並將Field數組綁定到該字段。一切都很好,保持狀態,實際上只需要很少的代碼。所以我從來不必動態地添加控件到頁面,謝天謝地。

感謝您的建議,Ender,Matt和andrewWinn。

2

由於沒有人對此進行了2個小時的刺探,所以我會用一種不依賴viewstate的解決方案(或者ASP.NET的模型回發)。

如果你用jQuery抓取所有的輸入值,而不是做一個後期做了一個針對該頁面(或新的results.aspx頁面)的帖子?或者,你可以讓整個事情變得異常,並且針對Web方法做一個Ajax請求,得到結果並根據需要填充到客戶端?

這裏不幸的是你必須重建哪種類型的控件用於構建搜索查詢,因爲該數據不會與視圖狀態一起傳遞。但是我想你已經不得不將輸入數據翻譯成查詢表單了。

閱讀here瞭解更多關於使用jQuery命中ASP.NET頁面方法的信息。記住 - 頁面方法必須是靜態的(這很容易忽略)。

我不確定你在做什麼服務器端來構建你的查詢 - 但我會高度推薦LINQ。我之前做了一個類似的「高級搜索」功能,經過幾次不同的嘗試後,發現LINQ對於這個問題來說是一個很棒的工具,無論我是在LINQtoSQL中使用SQL還是在內存中收集對象。

這很好,因爲1)LINQ是推遲執行和2)LINQ查詢返回另一個可查詢對象。這裏的含義是,您可以在您的輸入中構建LINQ查詢時將其鏈接在一起,而不是必須對SQL執行單個大量子句轉換或您正在使用的任何後端存儲(我的一個嘗試是使用字符串構造SQL子句,但仍然通過SQLParameters傳遞輸入數據以實現SQL注入保護 - 當手工製作LINQ的數量級更容易理解和實現時,它非常混亂和複雜)。

例如:

List<string> data; // or perhaps your a DB Context for LINQtoSQL? 

var query = data.Where(item => item.contains("foo")); 

if({user supplies length search option}) 
    query = query.Where(item => item.Length < 5); 

// etc, etc. 

// LINQ doesn't do anything until the query is iterated, at which point 
// it will construct the SQL statement without you worrying about details or parameter binding 
foreach(string value in query) 
    ; // do something with the results 

由於延遲執行和可查詢的返回類型,您可以連接LINQ查詢該表達式一天到晚讓它擔心實現細節(如轉換爲SQL查詢)在執行時間。

+1

在這裏評論我自己的答案,因爲這與問題/答案無關,並且非常有見地 - 但這是我放棄使用ASP.NET來支持ASP.NET MVC的原因之一。HTTP協議不是有狀態的,ViewState的ASP.NET模型實際上只是一個猴子補丁程序,可以在Web應用程序中獲得狀態。就這樣,你遇到了這些問題。儘管可能有一個真正的ASP.NET/postback解決方案,但涉及到的複雜性開始超過了好處。畢竟,你只是試圖發送數據回服務器!應該像餡餅一樣容易。 – Matt 2009-09-10 18:33:39

+0

感謝您抽出寶貴時間來解釋這一切。雖然它避免了ViewState的特定問題,但是它放棄了整個方法並引入了一些新的挑戰。這有點「當你擁有的只是一把錘子時,所有東西看起來都像個釘子」解決方案 - 這是我在jQuery上看到的一些原因。 – 2009-09-11 13:50:24

+0

也感謝關於API和DB方面的建議,我知道這與問題無關,但我很欣賞聽到關於該主題的另一個觀點。 – 2009-09-11 13:51:10

2

我無法爲您提供您需要做的確切步驟,但我強烈建議您查看一下asp.net頁面的生命週期。我一次創建了一個用戶控件作爲DLL。我必須在生命週期的特定步驟捕獲回發數據,並在其他步驟重新創建和重新綁定數據。此外,像viewstate這樣的想法也僅在某些點上可用。我知道我必須重寫On_init,On_prerender和其他一些方法。

對不起,我沒有更多的幫助,但我沒有與我(與老僱主)的代碼。我希望這有幫助。

2

如果要動態地將控件添加到控件樹中,則還需要將它們添加到Postpack中。只需調用在Page_Load或Page_Init上構建控件的方法,並且控件應保留在回發頁面上。