需求
實現todo表項的增、刪、改、查 70%
利用數據庫保存及恢復應用狀態 15%
學習使用第三方工具查看數據庫內容 5%
拓展:10%
進行圖片的存取,如每個表項的圖片狀態保存5%
在實驗報告中描述LocalFolder RoamingFolder等存儲位置的作用
在實驗報告中描述StringBuilder 的作用5%
整理:
1. 頁面右上角添加搜索框,實現(按Title)查找功能,以彈出消息框的形式返回查詢的信息。查找可以模糊查找,即Title包含了搜索詞即可。輸入*則返回全部。
2. 增刪改同步於數據庫
3. 保存圖片到數據庫
基礎知識
SQLite的使用
每一個database都是一個sqlite3
對象;
每一個語句都是一個sqlite3_stmt
對象;每個sqlite3_stmt
對象有它的生命週期。
Database Connection Handle
typedef struct sqlite3 sqlite3;
Each open SQLite database is represented by a pointer to an instance of the opaque structure named “sqlite3”. It is useful to think of an sqlite3 pointer as an object.
Constructors: sqlite3_open(), sqlite3_open16(), sqlite3_open_v2()
Destructors: sqlite3_close(), sqlite3_close_v2()
Prepared Statement Object
typedef struct sqlite3_stmt sqlite3_stmt;
An instance of this object represents a single SQL statement that has been compiled into binary form and is ready to be evaluated.
Think of each SQL statement as a separate computer program. The original SQL text is source code. A prepared statement object is the compiled object code. All SQL must be converted into a prepared statement before it can be run.
The life-cycle of a prepared statement object usually goes like this:
Create the prepared statement object using sqlite3_prepare_v2().
Bind values to parameters using the sqlite3_bind_*() interfaces.
Run the SQL by calling sqlite3_step() one or more times.
Reset the prepared statement using sqlite3_reset() then go back to step 2. Do this zero or more times.
Destroy the object using sqlite3_finalize().
Constructors: sqlite3_prepare(), sqlite3_prepare16(), sqlite3_prepare16_v2(), sqlite3_prepare_v2()
Destructor: sqlite3_finalize()
使用UWP時SQLite保存在本地的位置
說了半天使用SQLite開發,那麼我們創建出來的數據庫究竟在存放在哪裏呢?系統默認是放在這個路徑的:C:\Users(username)\AppData\Local\Packages(packagename)\LocalState,其中username當然就不用小編解釋了,當然就是您的用戶名嘍!packagename可以在工程目錄裏面的Package.appxmanifest文件裏查看
常用uri前綴
實驗過程
1.畫圖
由於對Layout不熟悉,畫圖都花了好久。。
2. 建立一個DbManager類
拿來主義地使用課件上的代碼即可。
在編寫返回多個結果的search函數時稍微遇到點小問題,查得
The result code SQLiteResult.DONE means sqlite3_step() has finished executing. **In your code snippet, if your data table still have rows need to read,
statement.Step()
will returnSQLiteResult.ROW
**result code, which means sqlite3_step() has another row ready to read, not finished.
此外再稍微修改TodoItem
,增加一個可寫入Id的構造器。
3. 爲應用程序添加Dbmanager的服務
上週做圖片綁定時爲了方便給todoItem增加了一個StorageFile字段,但是StorageFile
是沒辦法保存到DB中去的,因而又要修改TodoItem(增加字段filePath)了。
思路變成:
選擇圖片—保存到LocalFolder—將相應路徑寫入TodoItem。不完成這個就不能開始服務的添加。
修改TodoItem及株連(?)的代碼
由於只要有StorageFile對象就可以寫入本地,只修改ViewModel內部即可 。
這裏的保存事實上是一種複製。弄清楚這個,使用:
uwp storagefile copy to localfolder
進行搜索,就找到了很多相關答案。
winrt-c-sharp-copy-image-from-asset-to-localstorage
StorageFile file =...;
await file.CopyAsync(ApplicationData.Current.LocalFolder, "image.png");
4. 用StringBuilder編寫查詢結果
sb.AppendFormat("Title: {0} Description: {1} Time: {2}", i.title, i.description, i.date.ToString());
sb.Append('\n');
5. 啓動app時從數據庫創建listview
實現圖片從數據庫讀入的思路
使用filePath保存—-啓動app時在viewmodel同步listview—使用一個異步函數封裝同步操作,進行循環的大量的文件讀取,加載bitmapimage
實現:
其實根本不用保存filePath,因爲圖片都唯一對應item,而且名字就是item.id。
會出現問題的是圖片類型,此處有兩個選擇
1.加載時對多種類型進行測試
2.寫入todoitem
雖然說寫入todoitem好像也不是一個好選擇,但是測試類型的話太耗時了。還是選擇寫入Todoitem。
Debug
首先遇到的問題是,添加項時,如果不選擇圖片,一添加就會出錯。
即使在viewmodel的添加函數裏默認設置它的bitmapimage居然也不行。
——通過Debug工具查看變量值,犯了低級錯誤:在應該使用類成員的地方用了局部變量。
然後(StorageFileObject.fileType中是包含”.”的,不用自己添加。
之後開始測試數據庫部分。
1.增加/刪除
用可視化工具輔助。先尋找一下DB創建到哪兒去了。。
username/appdata/package/…
包名在manifest裏可以找到。
BUG_02:增加雖然調用了dbManager的函數,但是並沒有插入到數據庫中,不知道什麼原因。。明明跟樣例是一模一樣的。
—-原因也是很弱智,INSERT裏面我忘記插入Id字段了……只要schema不同插入都會失敗。。
2.查詢
注意通配符的語法.
WHERE Description LIKE '%'+@SearchTerm+'%'
而且通配時不用bind參數,要分情況處理。
3.更新
圖片綁定的部分需要處理一下……
BUG_03:查詢結果的dialog不知道爲什麼好像只能顯示一行,經過調試stringbuilder的內容明明是正確的。
—-還是弱智錯誤:應該使用.Content屬性,而不是.Title。
BUG_04:查詢爲空時沒有提示信息。
—–查詢按鈕增加處理即可。
BUG_05:Create之後form不清空。
—–done
BUG_06: 寫入數據庫的圖片格式和實際不匹配。
—–忘記修改DBmanager中的更新函數
BUG_07: 無法複製已存在的文件
—-複製前先檢查是否存在,用探測的方法。
var flag = StorageFile.GetFileFromPathAsync(pathToCopy);
if (flag == null)
await f.CopyAsync(ApplicationData.Current.LocalFolder, nameOfImg);
BUG_08:刪除後form不清空。
——done.
BUG_09: appbarbutton上的edit,點擊後子頁的圖片不改變
—–在Menuflyoutitem_Edit_Clicked處添加
佈局
太噁心了,佈局真的太噁心了,各種巨難控制。如果沒有出現想要的效果,一定要先刪除掉所有的width,margin,height,alignment等等參數!
更好的設計方法是從一開始先確定好結構,而不要邊測試邊修改,實在是太耗時了。而且由於XAML語言,嵌套grid會變得非常難讀且噁心。
感想
1.類比和推理的能力非常重要。
2.設計數據模型的時候要考慮清楚可擴展性,同時保存一些低級的原始數據,否則就會出現像這兩次這樣修改Todoitem的同時大面積修改應用的慘劇 。
3. 一定要弄清楚問題,纔可能找到更好的結果;但有時候問題也是在不斷的搜索中變清晰的,所以從搜索開始,再慢慢思考哪些結果是需要的
4. 不使用含有completed字段的表雖然能滿足作業需求,但顯然是不合理的。