【WinForm】 旅遊行程編輯器專案之功能塊2

功能塊2主要想實現資料庫的功能,讀取資料庫並提供搜尋、顯示欄位調整、進階條件調整等資料顯示篩選的功能,並實做圖片瀏覽器,包含顯示圖片、上傳、刪除、上下頁的功能。但這個專案會使用Stream + CSV的方式來實現,目前預計在第2個專案才會正式加入SQL的操作。

以CSV實現簡單資料庫存取


甚麼是CSV、CRUD?
在這個專案中。在這個專案中,筆者並沒有真的將Place API取到的資料寫進資料庫系統,而是寫成CSV格式。CSV是一種通用的檔案格式全名為Comma-Separated Values中文又稱逗號分隔值。若還是不明白,就去用Excel隨便在幾個欄位寫些內容,存成.csv再用記事本去打開應該就會明白了。CRUD則是四個英文單字的縮寫,Create(新增)Retrieve(查詢)Update(更新)Delete(刪除)。CRUD常在資料庫的內容中看到,其實不難理解,如果把資料庫簡單的想成是使用Excel,對表單也不外乎就是在執行上述的動作。

 

使用FileStream讀取csv檔
在.NET中提供了一個方便的指令FileStream,透過FileStream我們就可以對CSV檔進行新增、寫入文字及讀取文字(可讀寫檔案不只CSV)。

FileStream fs = new FileStream(“your path”, FileMode.OpenOrCreate, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
while(!sr.EndOfStream)
{
    console.WriteLine(sr.ReadLine());
}

 

使用Split將字串以逗號分割,就可以取出csv各欄位的資料,後續只要針對不同需求邏輯,自己寫method就可以像顯示資料庫資料、修改表單、搜尋等功能囉。

 

使用JaveScriptSerializer讀取json檔
因筆者希望關鍵字查詢只針對景點名稱,但又希望能對縣市、區、類型或有無去過作篩選,故寫了進階篩選條件的功能。使用者可以在查詢前進行設定,這樣才能下大範圍且複雜的篩選條件。縣市資料可以在網路上找到資料,而資料格式則是另一種很常見的資料格式,JSON全名為JavaScript Object Notation,JSON格式的資料會長的像這樣。

[
  {
    "districts":
    [
      {
        "zip":209,
        "name":"南竿鄉"
      },
      {
        "zip":210,
        "name":"北竿鄉"
      },
      {
        "zip":211,
        "name":"莒光鄉"
      },
      {
        "zip":212,
        "name":"東引鄉"
      }              
    ],
    "name":"連江縣"  
  }
]

透過物件({ })與陣列([ ])的區分,將資料一層一層的包覆,如果要找到子層的分類,就得像洋蔥一層一層的往內剝開,專有名詞叫「反序列化」,意即將JSON格式轉換為物件,反之將物件轉為JSON格式則叫「序列化」(參1)。(反)序列化的方法,筆者查到有三種(參2),選用JavaScriptSerializer()的方法完成,其他的等後續有時間再來玩玩看。在反序列化之前,要針對JSON的架構建立類別,先找出{ }底下的欄位,這裡的案例有name(縣市名)與districts(地區),但地區中又有另一個{ },分別是zip(區碼)與name(區名),故要另外建一個類別,建立完的類別會長這樣。

class Country
{
    public string name {get; set;}
    public districts[] districts {get; set;}
}

class districts
{
    public string zip{get; set;}
    public string name{get; set;}
}

此外還必須考量一個問題,因為縣市與市區是連動的,不同的縣市對應的市區會不一樣,故筆者對縣市ComboBox的寫了一個SelectedIndexChanged的event,再針對不同的縣市,動態的替換區域ComboBox的item。

 

圖片顯示


圖片顯示的功能,在網頁上比較常看到的基本功能,不外乎就是上下頁、專業點的可能有zoom in、zoom out、甚至還有圖片編輯的功能。筆者在這個專案中建立了上下頁、上傳及刪除的功能。上傳檔案到本機的功能透過OpenFileDialog就可以實現了。

上傳檔案到本地端
上傳檔案到本地端的功能,OpenFileDialog主要包含幾個重要的參數。

OpenFileDialog dialog = new OpenFileDialog();
dialog.Title = "儲存圖片至資料庫"                     //視窗的標題
dialog.InitialDirectory = ".\\"                    //開啟視窗時的目錄位置
dialog.Fileter = "JPEGS(*.jpg) | *.jpg; *.jpeg";    //|限制可以選擇的副檔名

筆者在固定的路徑底下新增資料夾,並以景點名稱命名,這樣就可以找到圖片要儲存的路徑了。但最近又想到一個問題,假設有兩個相同的景點名稱怎麼辦,當時實做的時候並沒有考慮到這個問題,所以日後應該會改成用placeid來命名資料夾。

 

圖片顯示相關按鈕的顯示邏輯
寫程式除了程式碼之外,對於使用者經驗也是非常重要的,因為對於不是撰寫該專案的工程師而言,每個人的使用習慣並不同,不設好防呆的話,一不小心就會產生奇怪的Bug,為此筆者利用Enabled及visible的屬性直接對Button作控制,Enabled與Visible分別決定按鈕是否可以按,以及是否要顯示在Form上,思考的邏輯如下

  1. 沒有圖片: 顯示「沒有圖片.jpg」、新增鈕、刪除鈕、上下頁鈕。
  2. 只有1張圖片: 顯示該圖片、新增鈕、刪除鈕、上下頁鈕
  3. 2張圖片以上(含): 顯示第一張圖片、新增鈕、刪除鈕、上下頁鈕。

 

其中上下頁的邏輯也得自行撰寫,給一個變數表示圖片的Index,以及知道路徑底下有多少圖片,重點如下

  1. 上一頁按鈕: 若Index=0,「上一頁按鈕」的Enabled為False,否則為True。按下「下一頁按鈕」時,要將「上一頁按鈕」的Enabled設為True
  2. 下一頁按鈕: 若Index=路徑下圖片數-1,Enabled為False,否則為True。按下「上一頁按鈕」時,要將「下一頁按鈕」的Enabled設為True

 

今天就介紹到這裡啦!有興趣的可參考功能測試影片

 

參考資料

  1. https://dotblogs.com.tw/berrynote/2016/08/18/200338
  2. https://ithelp.ithome.com.tw/articles/10194713