中文字幕日韩一区二区_国产一区二区av_国产毛片av_久久久久国产一区_色婷婷电影_国产一区二区精品

WM有約(三):下一次是什么時(shí)候?

Written by Allen Lee

 

不要留戀過(guò)去

怎樣才能約束用戶,不讓其選擇過(guò)去的日期呢?有一個(gè)很傻的辦法,就是每次啟動(dòng)應(yīng)用程序的時(shí)候,自動(dòng)把MonthCalendar控件的MinDate屬性的值設(shè)為今天。這樣雖然禁止了用戶選擇過(guò)去的日期,卻帶來(lái)另外一些問(wèn)題:

  • 當(dāng)月之前的日期無(wú)法查看。
  • 和選項(xiàng)窗體的Min Date設(shè)置相沖。

有鑒于此,我們采用另一種辦法,就是在用戶選中某個(gè)日期時(shí),判斷這個(gè)日期是否已經(jīng)過(guò)去,若是,則禁用Pin菜單項(xiàng),若否,則啟用Pin菜單項(xiàng)。那么,如何獲知用戶選中了某個(gè)日期?最簡(jiǎn)單的辦法就是使用MonthCalendar控件的DateChanged事件:

代碼 1

運(yùn)行應(yīng)用程序,你會(huì)發(fā)現(xiàn),當(dāng)我選中今天或者將來(lái)的日期時(shí),Pin菜單項(xiàng)是啟用的(圖1),而當(dāng)我選中過(guò)去的日期時(shí),Pin菜單項(xiàng)則是禁用的(圖2):

圖 1

圖 2

 

這(幾)天不要選

在繼續(xù)之前,我們有必要搞清楚,"排除某(幾)天"究竟是什么意思。在這里,"排除某(幾)天"并不是指禁止用戶選中那(幾)天,而是指那(幾)天不在計(jì)劃中,但我們很清楚,計(jì)劃趕不上變化,或許那(幾)天真正到來(lái)的時(shí)候又可以選了。

和之前的"釘住日期"相比,"排除日期"除了無(wú)需在MonthCalendar控件上有所反映之外,其它部分基本上是一樣的,它支持排除某天、連續(xù)的幾天和某個(gè)周末,用來(lái)保存被排除的日期的文件和應(yīng)用程序放在同一個(gè)文件夾里,應(yīng)用程序在啟動(dòng)的時(shí)候會(huì)檢查這個(gè)文件是否存在,如果不存在就創(chuàng)建一個(gè)空白的文件。從上面這些描述來(lái)看,"排除日期"和"釘住日期"在很大程度上共享著相同的代碼,于是,接下來(lái)就是考慮如何重用現(xiàn)有的代碼并實(shí)現(xiàn)新的功能。

首先要處理的是LoadPinnedDates和SavePinnedDates兩個(gè)方法(參見(jiàn)《WM有約(一):你好,CF》的代碼5和代碼6),我們提取這兩個(gè)方法的代碼,并創(chuàng)建兩個(gè)新的方法:

代碼 2

代碼 3

這樣,LoadPinnedDates和SavePinnedDates兩個(gè)方法就可以簡(jiǎn)化為分別對(duì)LoadDates和SaveDates兩個(gè)方法的調(diào)用了,而LoadExcludedDates和SaveExcludedDates兩個(gè)方法也可以如法炮制了。在著手實(shí)現(xiàn)這些方法之前,我們還需要提供一個(gè)東西,那就是文件的路徑,也是我們接下來(lái)需要做的事情——改造GetFilePath方法(參見(jiàn)《WM有約(一):你好,CF》的代碼4),改造后的GetFilePath方法將會(huì)用來(lái)映射文件路徑:

代碼 4

有了這些準(zhǔn)備,我們就可以著手實(shí)現(xiàn)LoadExcludedDates和SaveExcludedDates兩個(gè)方法了:

代碼 5

至于LoadPinnedDates和SavePinnedDates兩個(gè)方法的新版本就留給讀者自行處理了。

接著就是"排除日期"的核心功能——ExcludeWeekend和ExcludeRange兩個(gè)方法了,它們與PinWeekend和PinRange兩個(gè)方法(參見(jiàn)《WM有約(一):你好,CF》的代碼1和代碼2)的最大區(qū)別就是不需要把操作結(jié)果反映在MonthCalendar控件上,而它們的共同之處是都要計(jì)算具體的日期并把它們添加到對(duì)應(yīng)的集合里。我們先來(lái)看看計(jì)算具體的日期這部分功能,它分為兩種情況,一種是計(jì)算周末的,另一種是計(jì)算兩個(gè)日期之間的,如果這兩個(gè)日期相同,則視為一天,于是,我們可以創(chuàng)建CalculateWeekend和CalculateRange兩個(gè)方法來(lái)分別負(fù)責(zé)這兩種情況:

代碼 6

有了這些準(zhǔn)備,我們就可以著手實(shí)現(xiàn)ExcludeWeekend和ExcludeRange兩個(gè)方法了:

代碼 7

至于PinWeekend和PinRange兩個(gè)方法的新版本就留給讀者自行處理了。

還差什么呢?對(duì),用戶界面,沒(méi)有這個(gè),我們辛苦了這么久就白干了:

圖 3

還有Exclude菜單項(xiàng)的相關(guān)代碼:

代碼 8

噢,別忘了在InitializeFile方法(參見(jiàn)《WM有約(一):你好,CF》的代碼12)里添加檢查文件是否存在的代碼,以及在適當(dāng)?shù)牡胤教砑颖4鏀?shù)據(jù)的代碼,否則……

運(yùn)行應(yīng)用程序,選中2009年1月17日到2009年1月31日之間的日期,然后單擊Exclude菜單項(xiàng):

圖 4

通過(guò)資源管理器找到ExcludedDates.txt文件,然后用Word Mobile查看里面的內(nèi)容,結(jié)果發(fā)現(xiàn)只有下面3天!

圖 5

問(wèn)題出在哪里?原來(lái),我選中的那幾天的開(kāi)始日期恰好是星期六,于是應(yīng)用程序"自作聰明"地把它視為一般周末!如何解決這個(gè)問(wèn)題?回到代碼8,我們知道,ExcludeWeekend方法的調(diào)用需要滿足兩個(gè)條件,第一個(gè)是用戶只選中了一天,另一個(gè)則是這天是星期六。要知道用戶是否只選中了一天,我們只需要看看SelectionStart和SelectionEnd兩個(gè)屬性是否同一天:

代碼 9

再次運(yùn)行應(yīng)用程序,這次就正常了:

圖 6

需要提醒的是,Pin菜單項(xiàng)的相關(guān)代碼由于應(yīng)用了相同的邏輯,于是也存在相同的問(wèn)題,不過(guò)解決方法是一樣的,所以這里就不說(shuō)了。另外,因?yàn)?排除日期"不像"釘住日期"那樣會(huì)在用戶界面上有所反映,所以當(dāng)我們單擊Exclude菜單項(xiàng)時(shí),一切都在后臺(tái)完成,如果用戶不知情的話,感覺(jué)起來(lái)就像什么也沒(méi)干一樣,為了增強(qiáng)用戶體驗(yàn),最好就顯示一個(gè)消息框告訴用戶日期已被排除。

 

這(幾)天應(yīng)該選

由于"包含日期"和"排除日期"極其相似,再加上我們?cè)趯?shí)現(xiàn)"排除日期"時(shí)提取的公共代碼也適用于"包含日期",于是,我們可以用非一般的速度來(lái)實(shí)現(xiàn)"包含日期"的內(nèi)部邏輯:

代碼 10

至于用戶界面,我們同樣為它添加一個(gè)Include菜單項(xiàng):

圖 7

而這個(gè)菜單項(xiàng)的相關(guān)代碼如下:

代碼 11

其它東西,例如應(yīng)用程序啟動(dòng)的時(shí)候檢查用來(lái)保存日期的文件是否存在、讀取保存的日期和在適當(dāng)?shù)臅r(shí)候保存日期,和前面的實(shí)現(xiàn)大同小異,這里就不細(xì)說(shuō)了。

運(yùn)行應(yīng)用程序,選中2009年2月14日,然后單擊Include菜單項(xiàng):

圖 8

由于這天剛好是星期六,所以應(yīng)用程序執(zhí)行了包含周末的邏輯,這也是預(yù)期的行為:

圖 9

到了這里,你可能會(huì)認(rèn)為"排除日期"和"包含日期"也是時(shí)候告一段落了,但事實(shí)上我們還有一個(gè)問(wèn)題需要處理。試想一下,如果我對(duì)同一個(gè)日期先后執(zhí)行包含和排除操作,那么應(yīng)用程序是否應(yīng)該分別在m_IncludedDates和m_ExcludedDates兩個(gè)集合里登記這個(gè)日期?我們知道,"排除日期"和"包含日期"都是用來(lái)反映計(jì)劃的調(diào)整,比起分別在兩個(gè)地方登記同一個(gè)日期,執(zhí)行抵消操作或許更有意義。舉個(gè)例子,剛才我包含了2009年2月14日,現(xiàn)在我要排除這個(gè)日期,那么應(yīng)用程序應(yīng)該從m_IncludedDates里刪除這個(gè)日期而不是向m_ExcludedDates添加這個(gè)日期。怎么樣?是不是很簡(jiǎn)單?然而,這個(gè)東西實(shí)現(xiàn)起來(lái)一點(diǎn)都不容易,因?yàn)槲覀兺ǔ2僮鞯氖且唤M日期而不是單個(gè)日期,如果我們足夠好運(yùn),那么要抵消的日期集合會(huì)是被抵消的日期集合的子集,如果我們不夠運(yùn)氣,那么……一般地,如果我們要包含一組日期,那么我們要先檢查m_ExcludedDates是否包含了這些日期的部分或全部,如果是,則從m_ExcludedDates里刪除相同部分,剩下的才添加到m_IncludedDates。以IncludeWeekend方法(參見(jiàn)代碼10)為例,從最初的monthCalendar1.SelectionStart到最后的m_IncludedDates.AddRange需要經(jīng)過(guò)如下四步:

圖 10

其中,第三步的Subtract方法是解決這個(gè)問(wèn)題的關(guān)鍵,那么,如何實(shí)現(xiàn)這個(gè)方法呢?我們知道,List本身沒(méi)有提供這個(gè)方法,要想達(dá)到這樣的效果就得使用C# 3.0的擴(kuò)展方法了。下面來(lái)看看我的實(shí)現(xiàn):

代碼 12

對(duì)于second里的每個(gè)日期,Subtract方法試圖從first里刪除,并通過(guò)Remove方法的返回值判斷刪除操作是否成功,如果不成功,就意味著這個(gè)日期應(yīng)該添加到m_IncludedDates里,于是返回這個(gè)日期。有了這些準(zhǔn)備,我們就可以著手修改IncludeWeekend方法:

代碼 13

另外,IncludeRange、ExcludeWeekend和ExcludeRange等方法也需要修改,不過(guò)都是大同小異,所以就不一一列舉了。

 

下一次是什么時(shí)候?

下一次……在MonthCalendar控件下面……

圖 11

通常,這種可預(yù)測(cè)的"下一次"都意味著計(jì)算周期的存在,對(duì)于這個(gè)應(yīng)用程序,這個(gè)周期是兩周,以星期六為計(jì)算基準(zhǔn),比如說(shuō),假設(shè)上圖的5、6和7三天已被釘住,那么 下次應(yīng)該被釘住的日期將會(huì)是19、20和21三天,于是"Next time:"下面的Label就應(yīng)該顯示"2008年12月19日"。這個(gè)計(jì)算過(guò)程的一般形式如下圖所示:

圖 12

有了這些分析,我們就可以著手實(shí)現(xiàn)CalculateNextTime方法了:

代碼 14

故事到此結(jié)束了嗎?當(dāng)然不是,前面我們花了這么多精力來(lái)實(shí)現(xiàn)"排除日期"和"包含日期",如果僅僅用來(lái)保存一些日期,那么我也未免太無(wú)聊了。

首先,我們來(lái)看看"包含日期"將會(huì)如何影響"下一次"的計(jì)算,還是借用圖11,假設(shè)19、20和21三天已被釘住,今天是23號(hào),那么"Next time:"下面的Label應(yīng)該顯示"2009年1月2日",但如果26、27和28三天已被包含,那么"Next time:"下面的Label就應(yīng)該顯示"2008年12月26日"了。簡(jiǎn)而言之,在時(shí)間軸上排在前面的"包含日期"將會(huì)取代使用默認(rèn)算法計(jì)算出來(lái)的日期:

代碼 15

接著,我們?cè)賮?lái)看看"排除日期"將會(huì)如何影響"下一次"的計(jì)算,假設(shè)2、3和4三天已被釘住,今天是6號(hào),那么"Next time:"下面的Label應(yīng)該顯示"2009年1月17日",但如果17到31之間的日期已被排除,那么"Next time:"下面的Label就應(yīng)該顯示"2009年2月7日"了。

圖 13

簡(jiǎn)而言之,"排除日期"會(huì)導(dǎo)致使用默認(rèn)算法計(jì)算出來(lái)的日期逐周往后推,直到計(jì)算出來(lái)的日期沒(méi)被排除為止:

代碼 16

由此可見(jiàn),完整的CalculateNextTime方法應(yīng)該包含如下四步:

圖 14

其中,第一步和第四步是從代碼14里分解出來(lái)的:

代碼 17

有了這些準(zhǔn)備,我們就可以著手實(shí)現(xiàn)完整的CalculateNextTime方法了:

代碼 18

最后,終于到最后了,我們要把計(jì)算結(jié)果顯示在應(yīng)用程序主窗體的"Next time:"下面,那么,我們應(yīng)該在什么時(shí)候顯示呢,又應(yīng)該在什么時(shí)候更新呢?用Activated事件!你可能會(huì)問(wèn),為什么不用Load事件呢?這是因?yàn)楫?dāng)用戶單擊應(yīng)用程序右上角的關(guān)閉按鈕時(shí),應(yīng)用程序?qū)嶋H上只是最小化到后臺(tái),當(dāng)用戶通過(guò)菜單或者其它方式再次啟動(dòng)應(yīng)用程序時(shí),實(shí)際上只是把應(yīng)用程序"還原"到前臺(tái),而在這個(gè)過(guò)程里L(fēng)oad事件并不會(huì)被觸發(fā)。事不宜遲,讓我們完成本集的最后一段代碼吧:

代碼 19

運(yùn)行應(yīng)用程序,終于看到下一次是什么時(shí)候了:

圖 15

 

你還想要什么?

在這本集里,我們花費(fèi)巨大精力實(shí)現(xiàn)"下一次"的計(jì)算,然而,"除了'現(xiàn)在',你永遠(yuǎn)不能生活在任何其他時(shí)刻,你所能得到的只是現(xiàn)在的時(shí)光,未來(lái)在到來(lái)時(shí)也只不過(guò)是另一個(gè)現(xiàn)在"([美]韋恩·W·戴爾,《你的誤區(qū)》),好好把握每一個(gè)"現(xiàn)在",你將會(huì)得到一個(gè)滿意的軌跡。

到目前為止,應(yīng)用程序的用戶界面都是為"垂直"屏幕設(shè)計(jì)的,有沒(méi)有想過(guò),假如用戶旋轉(zhuǎn)設(shè)備的屏幕,使之變成"水平"的,將會(huì)發(fā)生什么事情呢?下一集,我們將會(huì)探討這個(gè)問(wèn)題及其解決方案,我們還會(huì)嘗試創(chuàng)建用戶控件來(lái)封裝MonthCalendar控件、"下一次"Label以及相關(guān)的代碼,如果"時(shí)間"允許的話,我們還會(huì)看看如何在這個(gè)用戶控件上實(shí)現(xiàn)數(shù)據(jù)綁定。

相關(guān)文章:

WM有約(一):你好,CF

WM有約(二):配置信息

 

NET技術(shù)WM有約(三):下一次是什么時(shí)候?,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 成人福利网 | 成人在线视频网 | 久久久久久高潮国产精品视 | 天天拍天天插 | 国产精品美女久久久久aⅴ国产馆 | 黄色香蕉视频在线观看 | 在线看av网址| 日本aaaa| av黄色免费 | 久久骚 | 国产高清自拍视频在线观看 | 91视频在线看 | 亚洲国内精品 | 日韩三区在线 | 日本又色又爽又黄的大片 | 亚洲免费网址 | 久久久久久免费看 | 在线一区视频 | 99一区二区| 久久婷婷国产麻豆91 | 国产高清视频一区 | 久久久噜噜噜www成人网 | 九九综合 | 成人免费视频播放 | 日韩中文字幕一区二区 | 免费观看一级毛片视频 | 欧美日本在线观看 | 成人在线观看黄 | 精品一区国产 | a毛片视频网站 | 国产伊人久久久 | 久久99一区二区 | 亚洲一区二区三区视频 | 亚洲一区二区三区四区五区中文 | 日本精品免费在线观看 | 国产视频精品在线 | 国产精品免费一区二区三区 | www.久久.com| 日本精品免费在线观看 | 日本一区二区三区视频在线 | 久久婷婷国产香蕉 |