ポンコツXAMLer奮闘記

C#(主にXAML)関連のメモ書きがメインです。

入力チェックの簡略化(コード紹介)

前回は単純な入力チェック機能を持ったクラスの概念を説明しました。

nakasato-work.hatenablog.com

今回は、実際にコードの落とした場合の説明をします。
というか、ライブラリ化してGitHubに乗せたので、ダウンロードしましょう。

github.com

NCoreプロジェクトのValue配下がバリュークラス一式です。

AGenValueが抽象化された大本のクラスです。

その他、CGen~と命名されたクラスが、実際の値を持つクラスになります。

基本的に、ベースクラスに処理を詰め込まず、継承して機能を追加しましょう!

昔々、あるところに、同じ思想を抱いた方がいましたが、何を思ったのか、ベースクラスに集約しよう!とか言って、以下のような大罪を犯してしまいました。

class CValue
{
  public EDataType DataType;
  public int IntValue = 0;
  public double DoubleValue = 0;
  public string StringValue = "";
  public TimeSpan TimeValue;

  public bool SetValue(EDataType dataType, string str)
  {
    bool success = false;

    switch(dataType)
    {
      case eDouble:
        success = double.TryParse(str, out this.DoubleValue);
        break;
      case eInt:
        success = int.TryParse(str, out this.IntValue);
        break;
      case eString:
        this.StringValue = str;
        success = true;
        break;
      case eTime:
        success = TimeSpan.TryParse(str, out this.TimeValue);
        brea;
      default: //何もしない
        break;
    }

    return success;
  }
}

class CTimeValue : CValue
{
  public CTimeValue()
  {
    this.DataType = EDataType.eTime;
  }
}

ぱっと見問題ないように見えるこちらのソース。
よくよく考えると、非常によくないです。
あなたにこのソースの問題点がわかるでしょうか?
これの問題点がわかると、あなたのOPPレベルは格段に向上するでしょう。
(ほんと、これにすごい苦しみを与えられました。。。)

・継承による拡張性
・処理はあるべきクラスに配置する

という原則を守らないと、規模が大きくなったときに、トレースが大変になるので注意が必要です。
コアな部分は後で変更するのは難しいものです。
どこまでをベースクラスに置いて、どこまでを委譲するかは経験と嗅覚とゲーマーの感にゆだねられます。
(この辺がOPP指向の難しいところで、日本人がビビッて使いたがらないところの原因ですかね)


さて、話を戻しましょう。


実は上で紹介したGitHubリポジトリに、デモアプリも入っています。
NCoreDemoがそれですね。

使い方はいたって簡単!

まずはViewModelを以下のように定義します。

class CViewModel : BindableBase
{
    protected CGenDec _ItemValue = new CGenDec("ItemValue", "ItemValue", "%", 0, -10, 110, 1, true);

    public CGenDec ItemValue
    {
        get { return this._ItemValue; }
        set { this.SetProperty(ref this._ItemValue, value); }
    }

    protected CGenStr _ItemName = new CGenStr("ItemName", "ItemName", "input here!", 0, 10, true);

    public CGenStr ItemName
    {
        get { return this._ItemName; }
        set { this.SetProperty(ref this._ItemName, value); }
    }

    public CViewModel()
    {
        ItemName.ShowMessage += ItemName_ShowMessage;
        ItemValue.ShowMessage += ItemValue_ShowMessage;
    }

    private void ItemName_ShowMessage(AGenValue arg1, Exception arg2)
    {
        MessageBox.Show(arg2.Message);
    }

    private void ItemValue_ShowMessage(AGenValue arg1, Exception arg2)
    {
        MessageBox.Show(arg2.Message);
    }
}

次に、XAMLバインドします。

<Label Content="{Binding ItemName.Name}" IsEnabled="{Binding IsItemEnable.Value}"/>
<TextBox Text="{Binding ItemName.Text}" IsEnabled="{Binding IsItemEnable.Value}"/>
<Label Content="{Binding ItemValue.Name}" IsEnabled="{Binding IsItemEnable.Value}"/>
<TextBox Text="{Binding ItemValue.Text}" IsEnabled="{Binding IsItemEnable.Value}"/>

これだけで入力チェックができて、メッセージボックスまで表示できてしまいます!
簡単でしょ?

今回はここまでとします。
よいOPP生活を!