2013-06-24 52 views
3

我正在WPF中使用MVVM進行項目工作,我想在其中使用虛構的日曆。我希望這一年的時間長達100天,並且可以分成兩個季節而不是幾個月。據我所知,DateTime不能做到這一點,我自己實施它有一些麻煩(主要是我認爲我的方法是遠非理想)。任何建議,你可以給我,這將有助於得到這個工作將不勝感激。實現虛構的日曆格式

public enum Season { Dry, Rainy } 
public class Date : ObservableObject 
{ 
    #region Members 

    private int _year; 
    private int _dayOfYear; 
    private Season _season; 
    private string _displayDate; 

    #endregion 

    #region Properties 

    public int Year 
    { 
     get { return _year; } 
     set { _year = value; } 
    } 

    public int DayOfYear 
    { 
     get { return _dayOfYear; } 
     set 
     { 
      if (_dayOfYear == value) 
       return; 
      _dayOfYear = value; 
      RaisePropertyChanged(() => DayOfYear); 
     } 
    } 

    public Season Season 
    { 
     get 
     { 
      if (_dayOfYear < 70) 
       return Models.Season.Dry; 
      else 
       return Models.Season.Rainy; 
     } 
     set { _season = value; } 
    } 

    public string DisplayDate 
    { 
     get 
     { 
      return (_dayOfYear.ToString() + " Season of " + _season.ToString() + " " + _year.ToString()); 
     } 
     set 
     { 
      if (_displayDate == value) 
       return; 
      _displayDate = value; 
      RaisePropertyChanged(() => DisplayDate); 
     } 
    } 

    #endregion 
} 

在視圖模型:

public string Date 
{ 
    get { return DataManager.Data.Date.DisplayDate; } 
    set 
    { 
     if (DataManager.Data.Date.DisplayDate == value) 
      return; 
     DataManager.Data.Date.DisplayDate = value; 
     RaisePropertyChanged(() => Date); 
    } 
} 

的用戶界面將顯示的字符串,但從來沒有更新。當我更新日期時,「DayOfYear」二傳手會發射,但這就是發生的一切。

我會想象這不是一個很好的方式去做這件事。如果有人有MVVM友好的方式來實現自定義日曆樣式,我很想學習它。

回答

0

我建議你在內部使用int來代表這一天。每天,增加由1的值。然後,計算一年中,您有:

int year = day/100; 

和季節:

Season season = (day % 100) < 70 ? Season.Dry : Season.Rainy; 

這將是這個樣子:

public class MyCustomDate 
{ 
    private int _day; 

    public int Year 
    { 
     get { return _day/100; } 
    } 

    public Season Season 
    { 
     get { return (DayOfYear < 70) ? Season.Dry : Season.Rainy; } 
    } 

    public int DayOfYear 
    { 
     get { return _day % 100; } 
    } 

    // Create a date, given the year and the day within the year. 
    public MyCustomDate(int year, int day) 
    { 
     _day = (100 * year) + day; 
    } 

    public override string ToString() 
    { 
     return string.Format("{0} {1}, {2}", DayOfYear, Season, Year); 
    } 
} 

您可以添加其他屬性和方法來計算兩個日期之間的差異,從日期,季節和年份創建日期,將日期添加到日期等。關鍵是要在幾天內完成所有計算。僅使用季節和年份進行輸入和輸出。

我建議你讓你的自定義類不可變。如果您將其設置爲可變(例如,您可以設置Season),那麼您必須添加大量驗證代碼。考慮55 Dry 2012的日期。如果您將季節更改爲Rainy,那麼您的日期無效,因爲雨季只有30天。如果你設置大於99的日子,同樣的事情會發生。你最好在構造函數中完成所有的驗證。

不是說你不能擁有屬性設置器,只是我不會推薦它。但是,我認爲一個不可改變的類型可能會給可觀測性帶來麻煩?我對可觀察的說法不夠了解。

+0

這看起來像我需要在這種情況下采取的方向。現在我只需要弄清楚如何讓UI中的綁定起作用。 –

+0

這有一些漏洞(例如,在第100天讀取第2年第0天),但它似乎最接近我所需要的,所以我會繼續接受它。謝謝你的幫助。 –

+0

@JasonD:將'DayOfYear'計算更改爲'return(_day%100)+1;' –

4

那麼,你沒有看到顯示值變化的原因是因爲在DisplayDate的獲得者中,根本不使用_displayDate的值。所以你改變了_displayDate,然後提出屬性改變了,但是它只是檢索與之前相同的字符串。

話雖這麼說,有一些你需要考慮基本面:

  • 在幾乎任何語言或平臺,並在淨尤其,日期和時間類型被實現爲值類型。它們是不變的結構。你的實現被設計爲一個可變的,可觀察的類。這是要求麻煩的,因爲你可能會將它們傳遞給值類型語義。

  • 除了只是一個字段的容器,值也是可排序的也很重要。這需要執行IComparable。這也意味着幕後通常只有一個領域。例如,DateTime只有一個內部爲64位整數的字段。

  • 如果您想要實現「日曆系統」的概念,還有很多需要考慮的事情。例如,你說一年是100天,但你沒有在任何地方實施。你的歲月的基礎是什麼?你定義了一個時代嗎?如何從已知的日曆(如ISO8601或格里曆日曆系統)轉換?日子是否分解成其他尺寸,例如幾周?你有「時區」還是每個人都使用相同的基礎,如UTC?我可以從字符串解析你的格式嗎?還有很多其他的。

如果您確實想要實現自定義日曆系統。這裏有兩條路,你可以去: