WM有約(四):處理屏幕旋轉
Written by Allen Lee
如果用戶旋轉屏幕……
首先,運行一下應用程序:
圖 1
接著,旋轉一下屏幕:
圖 2
噢,"下一次"被擠下去了,屏幕也出現了滾動條,然而,屏幕上仍有許多空白地方未被利用,怎么辦?
支持屏幕旋轉的控件
以前,patterns & pactices提供了一個Mobile Client Software Factory,里面有一個OrientationAware控件,可以幫我們應對這種情況。現在,Clarius Consulting提供了一個專門用來應對這個問題的Orientation Aware Control組件,下面我們將會探討如何使用Community Edition來解決這個問題。
安裝好Orientation Aware Control組件之后,Add New Item對話框里會有一個Orientation Aware Control:
圖 3
選中這個項,給它一個名字,然后單擊Add,你會得到一個空白的控件設計界面,把HomeForm上的MonthCalendar控件和兩個Label控件復制到HomeControl上,調整它們的位置,使它們居中:
圖 4
接著,右鍵單擊控件的空白處,選擇Rotate:
圖 5
控件的設計界面將會旋轉:
圖 6
這幅圖運行后的樣子實際上就是圖2,現在把控件上的東西重新調整一下:
圖 7
需要說明的是,我把控件的Size設為和HomeForm的一樣,豎著的和橫著的分別對應起來。然后,把控件旋轉回去,把它添加到HomeForm上,并把它的Dock屬性設為Fill:
圖 8
哎喲,有點不堪入目啊,不知道運行起來會不會也是這樣呢?好,我們來看看:
圖 9
圖 10
嗯,處理得還算不錯,雖然橫屏時還是出現了滾動條。注意,由于目前HomeControl只是一個空殼,所以之前實現的所有功能都不會在上面產生作用,當然就包括"下一次"沒有任何顯示了。
把業務邏輯的代碼分離出來
目前,用戶界面的代碼和業務邏輯的代碼糾纏在一起,HomeForm.cs里的代碼更是超過四百行,這無疑會為將來的維護帶來問題(雖然我不打算維護這個示范程序,但門面話還是要說一下的,哈哈),于是,接下來將會嘗試把用戶界面的代碼分離到HomeControl里,而業務邏輯的代碼將會創建一個新的DateManager類來存放。
DateManager類將會負責日期的存取、文件管理和預測邏輯;而HomeControl將會負責MonthCalendar上釘住日期的更新、"下一次"的更新和獲取用戶選中的日期。
首先是文件管理,HomeForm.cs里的InitializeFile、GetPinnedDatesFilePath、GetExcludedDatesFilePath、GetIncludedDatesFilePath和GetFilePath等方法可以直接復制到DateManager類里,其中InitializeFile將會在DateManager類的構造函數里調用,以便創建用來儲存日期的文件。
接著是日期的存取,HomeForm.cs里的LoadDates、SaveDates、LoadPinnedDates、SavePinnedDates、LoadIncludedDates、SaveIncludedDates、LoadExcludedDates和SaveExcludedDates等方法都可以直接復制到DateManager類里,然而,由于DateManager類是用戶界面中立的,于是需要對外提供Load和Save兩個方法,以便相關的窗體/控件調用:
代碼 1
最后就是"下一次"的預測了,HomeForm.cs里的CalculateNextTime、CalculateNextSaturday、ApplyInclusion、ApplyExclusion和ApplyAdjustment等方法都可以直接復制到DateManager類里,另外,我們需要把CalculateNextTime方法變成公有方法,以便HomeControl調用。
慢著!我怎么添加日期?噢,差點忘記了~~~我們知道,DateManager并不需要關心你是否在添加一個周末,它的任務只是把你給它的一組日期添加到對應的集合,于是我們可以這樣實現Pin、Include和Exclude三個方法:
代碼 2
再等等!我怎么獲取要顯示在MonthCalendar上的釘住日期?很簡單,只需要提供一個PinnedDates屬性就可以了:
代碼 3
把用戶界面的代碼分離出來
我們知道,HomeControl的職責是顯示釘住日期、更新"下一次"和在用戶選中日期時發出通知,對于前兩個,我們只需簡單地提供兩個屬性就可以了:
代碼 4
對于后面那個職責,我們需要提供一個SelectedDatesChanged事件,它會在MonthCalendar控件的DateChanged事件的基礎上加上是否為周末的判斷邏輯。為了實現這個事件,我們需要創建一個SelectedDatesEventArgs類:
代碼 5
其中,CalculateWeekend和CalculateRange兩個方法是從HomeForm.cs里直接復制過來的。有了這些準備,我們就可以著手實現SelectedDatesChanged事件了:
代碼 6
還差什么呢?對了,是配置信息的設置,把HomeForm.cs里的SetupOptions方法直接復制過來,并把它變成公有方法。
最后就是著手整理HomeForm.cs了。首先,應用程序啟動的時候,我們需要設置HomeControl的配置信息,并調用DateManager的Load方法:
代碼 7
當主窗體的Deactivate事件觸發時和用戶單擊Save菜單項時,調用DateManager的Save方法:
代碼 8
當主窗體的Activated事件觸發時,更新HomeControl上的"下一次":
代碼 9
當用戶通過OptionForm修改了配置信息時,調用HomeControl的SetupOptions方法讀取配置信息:
代碼 10
當用戶在HomeControl里的MonthCalendar上做出選擇,我們將會把用戶選中的日期保存到一個私有變量里,然后根據SelectedDatesEventArgs的ArePast屬性設置Pin、Include和Exclude三個菜單項的Enable屬性:
代碼 11
當用戶單擊Pin、Include和Exclude三個菜單項時,將會調用DateManager對應的方法來處理:
代碼 12
最后,HomeForm.cs里的其他代碼,包括輔助方法和原用戶界面上的控件都要刪除。
現在,是時候運行一下應用程序了,看看改了這么多有沒有改壞了:
圖 11
噢,釘住日期沒有顯示出來!沒問題,只需要在主窗體的Activated事件觸發時和用戶單擊Pin菜單項時把DateManager的PinnedDates屬性的值賦給HomeControl的DataSource屬性就可以了。再次運行應用程序,這次就正常了(奇怪,為什么圖10上會多出一個滾動條呢?難道是因為之前沒有把窗體上原有的控件刪除?):
圖 12
圖 13
你還想要什么?
原本還想試一下數據綁定的,不過現在看來也沒有這個必要了。目前這個應用程序基本上可以投入應用了,所以下一步就是如何把它部署到設備上。下一集,我們將會探討如何為這個應用程序開發安裝包。
相關文章: