0

モデル RawValues に強く型付けされたビューがあります。このビューでは、Capsule (別のモデルである Capsule モデルで定義されている) のリストを含む DropDownList が必要です。選択した Capsule を RawValues モデルの CapsuleFk プロパティにバインドしたいと考えています。

RawValues モデルをスキャフォールディングするときに、さまざまな Capsules を含む DropDownList (@Html.DropDownListFor) をビューに自動的に生成する方法を見つけようとしています。DropDownList の項目は、4 つのレコードを含む Capsule テーブルから取得されます。以下にForeignKey、プロパティに属性を設定する方法を示しpublic int? CapsuleFkます。ビューに表示しているモデルを次に示します。このモデルの下に Capsule モデルが表示されます。

namespace CapWorx.QuikCap.Models
{
    public class RawValues
    {
        [Key]
        public int Pk { get; set; }

        public int? FillerFk { get; set; }
        [ForeignKey("FillerFk")]
        public virtual Filler Filler { get; set; }

        public int? CapsuleFk { get; set; }
        [ForeignKey("CapsuleFk")]
        public virtual Capsule Capsule { get; set; }

        public int Active1 { get; set; }
        public int Active2 { get; set; }
        public int Active3 { get; set; }
        public int Active4 { get; set; }
        public int Active5 { get; set; }
        public int KeyActive { get; set; }
        public int KeyActivePackStat { get; set; }
        public bool E4M { get; set; }
        public bool K100M { get; set; }
        public string CreatedBy { get; set; }
        public DateTime CreatedDate { get; set; }
    }
}

カプセルモデルは次のとおりです。

namespace CapWorx.QuikCap.Models
{
    public class Capsule
    {
        [Key]
        public int Pk { get; set; }
        public string Name { get; set; }
    }
}

私が正しくしていないことが明らかであることを願っています。アプリを実行すると、(予想どおり) ローカル環境に SQL データベースが自動的に作成されます。これは、正しいように見える SQL Server Management Studio から直接取得した外部キ​​ー リレーションシップのスクリーンショットです。私の外部キー ベース テーブルが正しい (RawValues) こと、およびプライマリ キー ベース テーブルも正しいこと (カプセル) に注意してください。

ここに画像の説明を入力

カプセルのリストを含む RawValues ビューに DropDownList を作成し、選択したカプセルを RawValues モデルの CapsuleFk プロパティにバインドできるように、私が間違っていることを特定するのを手伝ってくれませんか?

ありがとう!

4

1 に答える 1

1

ビジネス オブジェクトまたはデータ オブジェクトをビューに直接バインドしようとすると、一般的な問題が発生します。ビューがバインドする「ViewModel」を作成することは、MUUUUCH のよりクリーンなソリューションであり、この ViewModel には、ビューがその UI に必要とするすべてのものが含まれます。

これが私が使用するパターンです。まず、ViewModel:

public class RawValuesEditingViewModel
{
    // Your primary ID
    public int Pk { get; set; }

    [Required]
    public int? SelectedCapsulePk { get; set; }

    // Other basic fields as needed for editing on this screen
    public int Active1 { get; set; }
    public int Active2 { get; set; }
    public int Active3 { get; set; }
    public int Active4 { get; set; }
    public int Active5 { get; set; }
    public int KeyActive { get; set; }
    // blah blah blah....

    // Use this as the source for your Dropdown List for the capsule choice
    public IEnumerable<SelectListItem> CapsulesToSelectFrom
    {
        get
        {
            return from cap in DatabaseRepository.GetAllCapsules() // or some kind of Repo here.
                   select new SelectListItem {
                       Text = cap.Name,
                       Value = cap.Pk.ToString(),
                       Selected = (cap.Pk == this.SelectedCapsulePk), 
                   };
        }
    }

    public RawValuesEditingViewModel()
    {
        // This constructor is parameter-less because the MVC model binder needs it this way to bind on post back.
        // You can alter this behavior, but it gets hairy.
    }

    // Call this method from your Controller to populate the ViewModel fields. 
    public void LoadModelFieldsFromDataObject(int pkToLoadFrom)
    {
        // get the underlying database object, from EF in your case.
        var rawValuesObj = DatabaseRepository.GetRawValueObjectById(pkToLoadFrom);

        // Map your RawValues data object fields to the RawValuesEditingViewModel fields as needed.
        // Only map the fields you want to present for editing.
        // Check out "AutoMapper" if you are tired of writing this kind of code :)
        this.Pk = rawValuesObj.Pk;
        this.SelectedCapsulePk = rawValuesObj.CapsuleFk; 
        // etc etc etc
    }

    public void ExecuteRawValuesUpdate(int pk)
    {
        // code to persist back to database goes here.
        // probably you will re-fetch the database object, update its fields from this ViewModels fields, then persist it back thru EF.
    }
}

そして、いくつかのクリーンなメソッドを介してこれらの EF エンティティを取得する作業を行うデータベース リポジトリ クラスが作成されます。

public static class DatabaseRepository
{
    public static List<Capsule> GetAllCapsules()
    {
        // your EF calls/whatever go here.
    }

    public static RawValues GetRawValueObjectById(int pk)
    {
        // your EF calls/whatever go here.
    }
}

気になる "RawValues" エンティティの ID をどのように渡すかはわかりませんが、クエリ文字列を介して渡されるコントローラー アクションのペアを次に示します。

public ActionResult RawValues(int pk) 
{
    var rawValuesVM = new ViewModels.RawValuesEditingViewModel();
    try
    {
        rawValuesVM.LoadModelFieldsFromDataObject(pk);
    }
    catch (Exception ex)
    {
        // however you wish to handle a bad lookup
    }
    return View(rawValuesVM);
}

[HttpPost]
public ActionResult RawValues(ViewModels.RawValuesEditingViewModel rawValuesVM, int pk)
{
    if (ModelState.IsValid)
    {
        try
        {
            rawValuesVM.ExecuteRawValuesUpdate(pk);
            // Redirect or something here.
        }
        catch (Exception ex)
        {
            ModelState.AddModelError(string.Empty, ex);
        }
    }
    return View(rawValuesVM);
}

最後に、View は に強くバインドされRawValuesEditingViewModel、通常のフィールドが表示されます。選択した Capsule のドロップダウンは次のようになります。

@Html.DropdownListFor(mode => model.SelectedCapsulePk, Model.CapsulesToSelectFrom)
于 2013-03-23T19:57:14.687 に答える