2012年7月2日 星期一

用ListView做一個搜尋引擎webform

本來下的標題是「用ASP.NET寫一個搜尋引擎網頁」
後來想想…好像沒有自已手動「寫」
都是靠Visual Studio軟體中的控制項自動生成的…
命名上還是老實點好了,題外話。

既然Visual Studio幫我們把繁雜的程式碼給生出來了
不好好地看一看這些程式碼怎麼對得起它呢?

◎以上程式範例AspNet39.aspx,如在頁框下不能操作,請開新視窗操作
◎如果有問題歡迎您提出,dnowba很需要有人和我一起討論

以下就大致上講一下利用ListView控制項製作搜尋引擎網頁的方式


頁面上的佈置

如下圖
image

上面都是從工具箱拉出來的控制項,重點在於,在資料呈現這一個部分,用哪個控制項來做比較好,如下圖,在「資料」這個索引標籤裡,和資料呈現有關的控制項,由上而下有DataList、DetailsView、FormView、GridView、ListView。老實說,沒有買書籍參考的話,這麼多個呈現形式會不大清楚「用的時機」。
image

如果要有一個學習歷程的話,我的歷程是從 GridView → DetailsView → FormView → ListView 。
利用GridView、DetailView製作Master-Details 主表明細這篇文章所言,GridView、DetailsView就是一種主從式的呈現方式。但用過前二者的都知道,畫面上比較死板,若是要有比較特別的layout的話,那麼就要用ListView、 FormView 的方式,ListView之於GridView、FormView之於DetailsView,差別是在於後者是系統自動用表格table的方式來生成的,所以在樣式上比較制式,而前者是用template的方式生成。

至於 DataList 的話我沒有學習太多,在Visual Studio開發軟體裡頭,它的年紀比ListView還要老,就好像GridView一樣,GridView的前身是DataGrid(在Visual Studio2010已經看不到了),當時使用上不像現在的GridView這麼好用,尤其是「資料繫結」的部分是自已要手寫程式處理。所以 DataList 感覺是比 ListView 還要更自由,因為大部分要自已手動處理,但是相對的就是,一些常用功能如分頁、排序…等功能也都要自食其力。

所以在資料呈現的部分學習的要點還蠻少,學起來蠻快的,而且理論上是相同,也就是說不管控制項怎麼變化(從DataGrid到GridView),好像只有一些小小的差異,不會今天學了明天又沒用了。反倒是重點回歸到最後,還是在整體版面設計(如果你兼網頁美工的話)以及資料庫設計(如果你兼資料庫設計的話)…也許從底下的製作你可以感覺的到那麼一點…


開始製作

在製作之前可以仿造別人做好的樣式來佈置控制項,像這樣的搜尋引擎,可以參考一下google的樣式。不過dnowba當然沒這麼偉大,做網頁搜尋的引擎,這邊的搜尋引擎指的是自已網站內文章搜尋的功能,在「輸入關鍵字後,按下搜尋就可以找到對應的標題或內文」,所以除了畫面,最重要的還是資料繫結的部分。
image

一、資料繫結部分

在ListView上「設定資料來源」,進入了select陳述式,先選擇要呈現的資料欄位,因為搜尋是一種條件式撈取資料的方式,所以要使用where子句,這也是databind的重點。

透過視窗,可以慢慢的構築子句內容,不用自已寫完整的句子,系統會自已拼湊(如下圖紅框就是系統自已生成),而下面這個句子的意思就是,在textbox控制項裡輸入關鍵式,再把Textbox的關鍵字放回資料表中。
image

以這個範例來說,做title資料欄位的搜尋。要搜尋的話最基本有兩種方式。
1、精確搜尋:SELECT * FROM [test] WHERE ([title] =  @title )
2、模糊搜尋:SELECT * FROM [test] WHERE ([title] LIKE '%' + @title + '%')
這個寫法和直接在資料庫上的寫法有一些不同,是ADO.NET 。@title的意思是個被包裝過的變數,可以防止資料隱碼攻擊。
不過在「運算子」的使用是一樣的。因為2是模糊搜尋,所以可以透過萬用字元(%)的協助。如果搜尋的字串是「now」,那麼title欄位資料裡是dnow 或是 now forever 或是 knowhow 都可以被搜尋到。

上面是單欄位式的搜尋,從上面的例子裡我們「的確」一行程式也不用寫,但是要「看得懂」啊,看得懂了我們才能做一些變化和調整。以上例來說,其html原始碼如下:

    <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
        ConnectionString="<%$ ConnectionStrings:dnowtestConnectionString %>" 
        
        SelectCommand="SELECT * FROM [test] WHERE ([title] LIKE '%' + @title + '%')">
        <SelectParameters>
            <asp:ControlParameter ControlID="TextBox1" Name="title" PropertyName="Text" 
                Type="String" />
        </SelectParameters>
    </asp:SqlDataSource>

行2的ConnectionString 就是和資料庫連接的內容,用字串參數的方式來連接。
行4的SelectCommand 就是陳述式內容,我們除了透過視窗互動來建構陳述句外,要做更多變化的話可以直接修改背後的html碼。
行5-7是select的參數,這裡就看資料繫結的來源是什麼。

透過觀察系統生成的原始碼,看得懂的話也就可以舉一反三了,如果我們要改成多欄位式的搜尋的話(輸入字串可以同時找title欄位和article欄位有沒有關鍵字),可以動手「修改」程式碼,以下就是修改後的內容:

    <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
        ConnectionString="<%$ ConnectionStrings:dnowtestConnectionString %>" 
        
        SelectCommand="SELECT * FROM [test] WHERE (([title] LIKE '%' + @title + '%') OR ([article] LIKE '%' + @article + '%'))">
        <SelectParameters>
            <asp:ControlParameter ControlID="TextBox1" Name="title" PropertyName="Text" 
                Type="String" />
            <asp:ControlParameter ControlID="TextBox1" Name="article" PropertyName="Text" 
                Type="String" />
        </SelectParameters>
    </asp:SqlDataSource>

直接到html原始碼修改後,如果再透過視窗互動的方式的話,在select陳述式就變成「自訂」,也就是自已寫了(如下圖)image

二、畫面修改部分

剛做完資料繫結,畫面上是沒有東西的,如下圖,還必須先選擇完樣板後才可以檢視樣版並加以設計。
image

如下圖,點開ListView上面的smartag並選擇要套用的內容,最後一步ListView上還可以分頁,這省了很多麻煩(以前datalist的時代,分頁可是要另外找別人分享的solution的)
image

做完了基本設定後,smartag上就會多了一個「目前檢視」的下拉選單,不同的時機會對應不同的樣板。有些樣板和GridView是相同的,不同的如第二個子選項「AlternatingItemTemplate」就是條列多項時,換項顯示不同的樣式。這個階段完成後,才可以做網頁測試。
image

檢視一下目前的成果,順道來看看有哪些地方需要修正的:

(1)一載入頁面時,畫面呈現「未傳回資料」(如下圖) ,邏輯上不大對,文字敘述的也有點怪。
可以用利用GridView、DetailView製作Master-Details 主表明細這篇文章裡的方式來修改資料繫結的時間點…並修改EmptyDataTemplate的文字內容…(此處略)
image

(2)輸入個關鍵字查查看,如下圖,我們輸入「報」這個字,非常好,資料已經呈現,但還有幾處待修正,是這篇文章的重點之一,以下二個重要的修改分項解釋:
image

a、修改時間顯示方式,時間後的日期是我們輸入的,不過時間上都是顯示「上午12:00:00 」這是sql資料庫的資料型別問題,因為當初定義test_time這個欄位時,給的型別是datetime,本身就會紀錄到日期+時間,所以透過ADO.NET連結後,自然而然的給的預設顯示方式就是完整顯示,也就是下拉選單的(無)這個選項。

如下圖,先到ListView的ItemTemplate畫面。然後選擇test_timeLabel這個控制項。編輯他的DataBindings
image

關於不同的資料型別及其資料顯示方式,例如我們將格式改成「文章日期:{0:d}」
如果有興趣再研究「為什麼」的話,請參考之前整理的文章:資料型別文字標示的控制項:Literal和Label
image

再來補充「雙向資料繫結」選項是什麼意思,簡單的說,如果只是唯讀的呈現畫面的話,就用單向(eval),如果這個listview還要提供修改、新增的功能的話,就要用雙向繫結(bind),在運算式上的差別就如下圖。不過test_time欄位在這裡是用label控制項的方式顯示,就算勾了雙向也是沒有用的,呈現的又不是textbox怎麼修改。
image

b、修改tilte的功能,讓使用者點選title後顯示該篇文章的「完整內容」
這個部分就像Master-Details主細表的功能,這裡示範用傳統HTML的Get與Post方法
因為要能點選連結,所以先把title上原來自動建置的label控制項的資料繫結拿掉避免畫面上重複呈現文字內容,多放一個HyperLink控制項,開啟資料繫結,因為控制項不同,所對應「可繫結的屬性」也不一樣,先選Text屬性,將資料繫`結好。
image

再來是設定HyperLink的NavigateUrl屬性,重點在格式的地方…透過HTTP來傳遞變數。(XXXX .aspx)後的符號「?」,就表示開始要傳變數了。
image

而接受變數的網頁,則用Request.QueryString(“變數名稱")的方式來接值,如上面格式,我們設定了一個新的網頁AspNet39_1.aspx來接這個值,在這個網頁上我們佈置一個FormView並設定資料繫結,重點在where的地方怎麼設定接值
image

整個sqlcommand如下
SELECT [id], [test_time], [class], [title], [summary], [article], [author] FROM [test] WHERE ([id] = @id)

到這裡就完成了Master-Details主細表的功能。

(3)修改分頁數pagersize,如果使用過GridView的話,GridView的分頁是做在控制項裡的,也就是pagersize是GridView的其中一個參數。不過在listview裡分頁的功能是一個單獨的控制項(也就是說可以應用在別的地方囉…但是怎麼應用哩?我還不會= =)。
image

所以要修改分頁數的話,就要到ItemTemplate裡去修改PageSize這個屬性了。
image

(4) 最後再檢視一次,發現在搜尋列舉項目後,只有「單數列」的樣式被修改了,這個部分很有趣,原來是ListView在template樣板設計上,刻意把單數列和雙數列的樣式設定給分開來,雙數列的設定是在前面提到的<AlternatingItemTemplate>裡頭設定,這就意味者,前面對<ItemTemplate>做的databinding,也要在<AlternatingItemTemplate>標記裡如法炮製…
image

從這篇文章的篇幅看來,databinding雖然不用動手寫完整的程式碼,但是bind來bind去的過程中還挺麻煩的,如果不去學習語法的話,這個部分可以再像之前做的一樣去調整日期、連結之類的bind格式;但如果學習到這麼一點精髓的話,其實我們直接去html程式原始碼去修改反而來得快很多…(前面databinding的流程熟一點也要個三分鐘,如果只接找上門挑戰背後語法,只要五秒就搞定),怎麼做呢?就是到原始碼把<ItemTemplate>標記裡的東西全給複製貼上copy&paste,然後把標記改成<AlternatingItemTemplate>就好了…
image

畫面呈現是最後的階段了,這個地方要呈現什麼資料?資料樣式怎麼做?等問題都要先想好,因為畫面一旦固定的話,日後想要多呈現某個資料的話,如果不會手動修的話,得整個樣式打掉重新做一次,如下圖,資料繫結只要一改動,就會跳出下面的視窗,如果要保留樣式的話,可千萬要按「否」
image

沒有留言:

張貼留言

Related Posts Plugin for WordPress, Blogger...
// Dnow Function