18

WPF/Silverlight を使用した MVVM にはかなり慣れていますが、これは MVC Web アプリケーションでの初めての試みです。

Entity Framework モデル (読み取り/書き込みアクションとビューを生成するテンプレート) の「サイト」モデル クラスから自動生成された TestSitesController というコントローラーを作成しました。私が変更した唯一のことは、いくつかのメソッドで Guid id = null のデフォルト パラメータがあった 3 つの場所でした。「= null」を削除しただけで、すべて正常に機能します。これが私が変更したものの例です

public ActionResult Delete(Guid id = null)
{
    //....
}

これはに変更されました

public ActionResult Delete(Guid id)
{
    //....
}

サイト モデルは、特別な SiteId、Abbreviation、および DisplayName ではありません。この質問では、できるだけ単純にしようとしています。わかりましたので、ウェブサイトを実行して htpp://.../TestSites/ に移動すると、すべてが完全に機能します。

すべてのビュー (作成、削除、詳細、および編集) が @model MVCWeb.MyEntities.Site を使用していることに気付きました。しかし、Index.cshtmlビューで、それが使用していることに気付きました

@model IEnumerable<MVCWeb.MyEntities.Site>

これは、生成されたテンプレートでは問題なく機能しますが、「複合ビュー モデル」を使用したいと思います。これは、MVVM の知識を混ぜようとしているところですが、可能であればそれに固執したいと考えています。私の考えでは、複合ビュー モデルは、1 つ以上のエンティティ モデルと SelectedSiteId などの追加のプロパティで構成されるビューに固有の単なるモデルです。

そこで、TestSitesViewModel という非常に単純な ViewModel を作成しました。

public class TestSitesViewModel
{
    //Eventually this will be added to a base ViewModel to get rid
    //of the ViewBag dependencies
    [Display(Name = "Web Page Title")]
    public string WebPageTitle;

    public IEnumerable<MVCWeb.MyEntities.Site> Sites;

    //Other Entities, IEnumberables, or properties go here
    //Not important for this example
}

次に、コントローラーに IndexWithViewModel というアクション メソッドを追加しました。

public ActionResult IndexWithViewModel()
{
    var vm = new TestSitesViewModel();
    vm.WebPageTitle = "Sites With Composite View Model";
    vm.Sites = db.Sites.ToList();

    return View(vm);
}

次に、Index.cshtml のコピーを作成し、新しい ActionResult メソッド名に合わせて IndexWithModel.cshtml という名前を付けました。のトップラインを変更しました

@model IEnumerable<MVCWeb.MyEntities.Site>

@model MVCWeb.Models.TestSitesViewModel

これをテーブル セクションの前に追加して、DisplayNameFor と DisplayFor をテストしました。

@Html.DisplayNameFor(model => model.WebPageTitle)
&nbsp;
@Html.DisplayFor(model => model.WebPageTitle)
<br />

を変更しました

@foreach (var item in Model) {

@foreach (var item in Model.Sites) {

今のところ、すべてのテーブル ヘッダーを含む tr セクションをコメント アウトします。データ注釈の Display 属性に示されているように、@Html.DisplayNameFor が「Web ページ タイトル」を使用する代わりに「WebPageTitle」の変数名を表示していることを除いて、すべてが完全に機能します。

[Display(Name = "Web Page Title")]
public string WebPageTitle;

また、テーブル ヘッダー情報を含む tr セクションにコメントを戻すと、model.Sites.Abbreviation、model.Sites[0].Abbreviation、およびその他のさまざまな組み合わせを試しましたが、エラーが発生しました。

<tr>
    <th>
        @Html.DisplayNameFor(model => model.Abbreviation)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.DisplayName)
    </th>
    <th></th>
</tr>

そこで何を使えばいいの?サイトは元の Index.cshtml でモデルとして使用されたのとまったく同じタイプであるため、model.Sites.Abbreviation が機能しない理由はよくわかりません。

4

2 に答える 2

23

数時間いじり回した後、ようやくこれを理解しました。

最初の問題は、Data Annotations で Display アーティビュートを使用するために、get および set アクセサー メソッドを追加する必要があります。たとえそれらがデフォルトのものだけであってもです。これは、クラスのパブリック データ メンバーではなく、プロパティでのみ機能する必要があるためだと思います。を取得するコードは次のとおりです。

@Html.DisplayNameFor(model => model.WebPageTitle)

正しく動作する

public class TestSitesViewModel
{
    //Eventually this will be added to a base ViewModel to get rid of
    //the ViewBag dependencies
    [Display(Name = "Web Page Title")]
    public string WebPageTitle { get; set; }

    //PUBLIC DATA MEMBER WON'T WORK
    //IT NEEDS TO BE PROPERTY AS DECLARED ABOVE
    //public string WebPageTitle;

    public IEnumerable<MVCWeb.MyEntities.Site> Sites;

    //Other Entities, IEnumberables, or properties go here
    //Not important for this example
}

問題の 2 番目の部分は、IEnumerable 変数でメタデータにアクセスすることでした。headerMetadata という一時変数を宣言し、IEnumerable を介してプロパティにアクセスしようとする代わりにそれを使用しました

@{var headerMetadata = Model.Sites.FirstOrDefault();}
<tr>
    <th>            
        @Html.DisplayNameFor(model => headerMetadata.Abbreviation)
    </th>
    <th>
        @Html.DisplayNameFor(model => headerMetadata.DisplayName)
    </th>
    ...

これは、headerMetadata 変数がいつスコープ外になるのかという疑問を投げかけます。ビュー全体で使用できますか、それとも html テーブル タグに限定されますか? それは別の日付の別の質問だと思います。

于 2013-04-12T20:18:24.000 に答える
1

新しく学んだ MVVM ASP.NET MVC の経験を試してみます。

を呼び出す代わりに、@Html.DisplayNameFor(model => model.WebPageTitle)を使用してみてください@Html.DisplayFor(model => model.WebPageTitle)。ビューに表示される IndexWithViewModel コントローラーで WebPageTitle 値を設定しているようです。

ASP.NET MVC の共有テンプレートを調べます。/Views/Shared/EditorTemplates/Site.cshtmlおよびで、DisplayFor/EditorFor ヘルパーのカスタム テンプレートまたはパーシャルを設定できます/Views/Shared/DisplayTemplates/Site.cshtml。ASP.NET MVC は、DisplayFor および EditorFor を使用して Site オブジェクトをレンダリングするときに、これらのテンプレートを自動的に取得します。

幸運を!

于 2013-04-12T16:53:05.417 に答える