2

プロパティの特定の値に応じて、異なる画像を表示する必要があります。
これがこのタスクを実行するための私の方法です。

私はモデルを持っています:

public class DetailInfoViewModel
{
    public string Status {get; set;}
    public string StatusImageName {get; set;}
    ... other fields
}

アクションで:

var model = ...// create view model and fill properties    
model.StatusImageName = GetImageFileNameForStatus(model.Status.ToLower());

そして、主な方法:

private string GetImageFileNameForStatus(string status)
{
    if (status == "payed" || status == "approved")
        return "payed.png";

    if (status == "printed")
        return "not-pay.png";

    if (status == "closed")
        return "closed.png";

    if (status == "transfer")
        return "transfer.png";

    return string.Empty;
}

ビューには、単純なhtmlがあります。

<div class="pull-right">
    <img src="@Url.Content("~/Images/" + Model.StatusImageName)"/>
</div>

しかし、この方法は醜いです。画像の名前を変更したり、誤植したりすると、このコードは正しく機能しません。
これを行うためのより良い方法はありますか?

4

2 に答える 2

1

エラーが発生しにくくするために、ステータスを列挙型にすることを検討してください

enum Status { Payed, Printed, Closed, Approved, Transfer}

そして、T4MVCを使用して、リソースへの強力なリンクを生成します。

private string GetImageFileNameForStatus(Status status)
{
    switch(status){
      case Payed:
      case Approved:
        // This is generated by T4MVC for you
        return Links.Content.Images.payed_png;
      case Printed:
        return Links.Content.Images.not_pay_png;          
      // ... etc.
      default:
        return Links.Content.Images.default_png;
    }
}

switchステートメントの代わりに、情報をの中に保存することもできますがDictionary<Status, string>、それは実装の詳細です。

その後、これと同様に使用できます。

<img src="@Model.StatusImageName" alt="@Model.Status"/>

注意:alt属性を追加することを忘れないでください!

画像の名前を変更したり移動したりすると、コンパイルが中断するようになりました。

このソリューションは、ほとんどの小規模なシステムで受け入れられるはずです。より複雑な「純粋なOOP」ソリューション(ユースケースによっては、過剰なエンジニアリングに悩まされる可能性があります)に興味がある場合は、このまま読み進めてください。

純粋なOOPの観点からは、このスイッチは(比較的単純ですが)最も美しいソリューションではありません。状態パターン.NET実装)を検討することもできます。

interface IStatus{
    string InfoImage{get;}
}

class PayedStatus : IStatus {    
    public string InfoImage{get{return Links.Content.Images.payed_png;}}
}

class PrintedStatus : IStatus {    
    public string InfoImage{get{return Links.Content.Images.not_pay_png;}}
}

// etc.

そしてあなたのモデル:

public class DetailInfoViewModel
{
  ... 
  public IStatus Status{get;set;}
}

あなたの見解では:

<img src="@Model.Status.InfoImage" alt="Status"/>

特定のステータスに固有のものがある場合、このアプローチはさらに優れています。特定のステータスに関連するすべてのものを、それぞれのIStatus実装内にきちんとカプセル化できます。

繰り返しになりますが、オブジェクト指向設計の観点からは、UIの詳細(表示する画像)がモデルの一部になるのは奇妙に感じます。一方、それはビューモデルなので、なぜですか。ダイハードOOPを実行したい場合、システムの複雑さと要件がそれを保証する場合は、Visitor Pattern.NET実装)を検討できます。

interface IStatusVisitor<T>{
   T VisitPayedStatus<T>(PayedStatus status);
   T PrintedStatus<T>(PrintedStatus status);
   // ...
}

interface IStatus{
    T Accept(IStatusVisitor<T> visitor);
}

class PayedStatus : IStatus {    
    public T Accept(IStatusVisitor<T> visitor){
        return visitor.VisitPayedStatus(this);
    }
}

class PrintedStatus : IStatus {    
    public T Accept(IStatusVisitor<T> visitor){
        return visitor.VisitPrintedStatus(this);
    }
}


class InfoImageVisitor : IStatusVisitor<string>{

  public string VisitPayedStatus(PayedStatus status){
    return Links.Content.Images.payed_png;
  }

  public string VisitPrintedStatus(PrintedStatus status){
    return Links.Content.Images.not_pay_png;
  }

}


<img src="@Model.Accept(new InfoImageVisitor())" alt="Status"/>

このようにして、情報画像に関するすべてを状態クラスから別のクラスに移動します。

しかし、私が言ったように、これはすでに過剰設計のケースと見なすことができます。システムの要件によって異なります。

一般的な注意として:デザインパターンを読むことは間違いなく価値があります。

于 2013-02-12T10:03:05.280 に答える
0

これが最善の方法かどうかはわかりませんが、imageNameをステータス名として定義できます。

status | statusImage |
----------------------
 payed |   payed.png |
closed |  closed.png |
   ... |         ... |

それで

<div class="pull-right">
    <img src="@Url.Content("~/Images/" + Model.Status) + ".png""/>
</div>
于 2013-02-12T09:36:53.090 に答える