3

架空のカレンダーを使用したい MVVM を使用して WPF でプロジェクトに取り組んでいます。1 年の長さを 100 日にして、月ではなく 2 つの季節に分けたいと思います。私が知る限り、これを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);
    }
}

UI には文字列が表示されますが、更新されることはありません。日付を更新すると、「DayOfYear」セッターが起動しますが、それだけです。

これはあまり良い方法ではないと思います。カスタムカレンダースタイルを実装するMVVMフレンドリーな方法を誰かが持っているなら、私はそれを学びたいです.

4

2 に答える 2

4

表示値の変更が表示されない理由は、 のゲッターで値をまったくDisplayDate使用しないためです_displayDate。を変更して_displayDateから、プロパティが変更されたことを上げますが、以前と同じ文字列を取得するだけです。

そうは言っても、考慮すべき基本事項がいくつかあります。

  • ほぼすべての言語またはプラットフォームで、特に.Net では、日付と時刻の型が値の型として実装されています。それらは不変の構造体です。実装は、可変で監視可能なクラスとして設計されています。おそらく値型のセマンティクスでそれらを渡すことになるため、これは問題を引き起こしています。

  • フィールドのコンテナであるだけでなく、値がソート可能であることも重要です。それには実装が必要IComparableです。また、通常は舞台裏で 1 つのフィールドが存在することも意味します。たとえば、DateTime内部的に 64 ビット整数であるフィールドが 1 つだけあります。

  • 「カレンダー システム」の概念を実装しようとしている場合は、考慮すべきことが他にもたくさんあります。たとえば、1 年は 100 日だと言いますが、それをどこにも実装していません。そして、あなたの年の基礎は何ですか?エポックを定義していますか?ISO8601 やグレゴリオ暦などの既知の暦からどのように変換しますか? 日は、週などの他のサイズに分割されますか? 「タイムゾーン」はありますか? それとも、UTC などの同じ基準を使用していますか? 文字列からフォーマットを解析できますか? 他にもたくさんあります。

カスタムカレンダーシステムを実際に実装したい場合。あなたが行くことができる2つのルートがあります:

于 2013-06-24T18:51:06.113 に答える
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);
    }
}

他のプロパティとメソッドを追加して、2 つの日付の差を計算したり、日、季節、年から日付を作成したり、日付に日数を追加したりできます。重要なのは、すべての計算を日数で行うことです。入力と出力には季節と年のみを使用してください。

カスタムクラスを不変にすることをお勧めします。変更可能にする場合 (つまりSeason、たとえば を設定できる場合)、大量の検証コードを追加する必要があります。の日付を考えてみましょう55 Dry 2012。季節を に変更するRainyと、梅雨は 30 日しかないため無効な日付になります。日を 99 よりも大きく設定しようとすると、同じようなことが起こります。そのすべての検証をコンストラクターで行う方がよいでしょう。

プロパティ セッターを使用できないと言っているわけではありませんが、お勧めしません。しかし、不変型が観察可能で問題を引き起こす可能性があると思いますか? 私はオブザーバブルについて言うのに十分な知識がありません。

于 2013-06-24T18:44:13.357 に答える