1

IEnumerableごとにRadioButtonのリストを含むビューを取得するモデルが定義されています。

そのモデル内で、選択したアイテムに基づいて変化するチェックボックスのリストを表示したいと思います。最後に、ユーザーが使用可能なチェックボックスから選択すると、同じビューにTextareaが表示され、選択されたチェックボックスに基づいて動的なテキストが表示されます。最終的には、階層ごとのテーブルになります。

レイアウトは、RadioButtonListが最初のテーブルセルにあり、CheckBoxListが中央のテーブルセルにあり、Textareaが右側のテーブルセルにあるようなものです。

誰かがこの結果を達成するために私のモデルビューがどうあるべきかについて私を導くことができれば、私は最も喜ぶでしょう...

これが私のコードです:

//
// View Model for implementing radio button list

public class RadioButtonViewModel
{
    // objects
    public List<RadioButtonItem> RadioButtonList { get; set; }
    public string SelectedRadioButton { get; set; }
}

//
// Object for handling each radio button

public class RadioButtonItem
{
    // this object
    public string Name { get; set; }
    public bool Selected { get; set; }
    public int ObjectId { get; set; }
    // columns
    public virtual IEnumerable<CheckBoxItem> CheckBoxItems { get; set; }
}

//
// Object for handling each checkbox

public class CheckBoxViewModel
{
    public List<CheckBoxItem> CheckBoxList { get; set; }
}

//
// Object for handling each check box

public class CheckBoxItem
{
    public string Name { get; set; }
    public bool Selected { get; set; }
    public int ObjectId { get; set; }
    public virtual RadioButtonItem RadioButtonItem { get; set; }
}

とビュー

@model IEnumerable<EF_Utility.Models.RadioButtonItem>

@{
    ViewBag.Title = "Connect";
    ViewBag.Selected = Request["name"] != null ? Request["name"].ToString() : "";
}

@using (Html.BeginForm("Objects" , "Home", FormMethod.Post) ){

@Html.ValidationSummary(true)

<table>
    <tbody>
        <tr>
            <td style="border: 1px solid grey; vertical-align:top;">

                <table>
                    <tbody>
                        <tr>
                            <th style="text-align:left; width: 50px;">Select</th>
                            <th style="text-align:left;">View or Table Name</th>
                        </tr>
                        @{
                        foreach (EF_Utility.Models.RadioButtonItem item in @Model )
                        {
                        <tr>
                            <td>
                                @Html.RadioButton("RadioButtonViewModel.SelectedRadioButton", 
                                    item.Name, 
                                    ViewBag.Selected == item.Name ? true : item.Selected, 
                                    new { @onclick = "this.form.action='/Home/Connect?name=" + item.Name + "'; this.form.submit(); " })
                            </td>
                            <td>
                                @Html.DisplayFor(i => item.Name)
                            </td>
                        </tr>
                        }
                        }
                    </tbody>
                </table>

            </td>
            <td style="border: 1px solid grey; width: 220px; vertical-align:top; @(ViewBag.Selected == "" ? "display:none;" : "")">

                <table>
                    <tbody>
                        <tr>
                            <th>Column
                            </th>
                        </tr>
                        <tr>
                            <td><!-- checkboxes will go here -->
                            </td>
                        </tr>
                    </tbody>
                </table>

            </td>
            <td style="border: 1px solid grey; vertical-align:top; @(ViewBag.Selected == "" ? "display:none;" : "")">
                <textarea name="output" id="output" rows="24" cols="48"></textarea>
            </td>
        </tr>
    </tbody>
</table>
}

および関連するコントローラー

public ActionResult Connect() 
    {
        /* TEST SESSION FIRST*/ 
        if(  Session["connstr"] == null)
            return RedirectToAction("Index");
        else
        {
            ViewBag.Message = "";
            ViewBag.ConnectionString = Server.UrlDecode( Session["connstr"].ToString() );
            ViewBag.Server = ParseConnectionString( ViewBag.ConnectionString, "Data Source" );
            ViewBag.Database = ParseConnectionString( ViewBag.ConnectionString, "Initial Catalog" );

            using( var db = new SysDbContext(ViewBag.ConnectionString))
            {
                var objects = db.Set<SqlObject>().ToArray();

                var model = objects
                    .Select( o => new RadioButtonItem { Name = o.Name, Selected = false, ObjectId = o.Object_Id, CheckBoxItems = Enumerable.Empty<EF_Utility.Models.CheckBoxItem>() } )
                    .OrderBy( rb => rb.Name );

                return View( model );
            }
        }
    }

私が見逃しているのは、データコンテキストを前面に出すConnect()メソッドのコードです。その時点で、ビューのHTMLを設定するのはかなり簡単なはずです。

編集**したがって、CheckBoxListが空のセットにならないことを除いて、RadioButtonItemを次のようなビューにバインドする必要があります。

    //
    // POST: /Home/Connect/

    [HttpPost]
    public ActionResult Connect( RadioButtonItem rbl )
    {
        /* TEST SESSION FIRST*/
        if ( Session["connstr"] == null )
            return RedirectToAction( "Index" );
        else
        {
            ViewBag.Message = "";
            ViewBag.ConnectionString = Server.UrlDecode( Session["connstr"].ToString() );
            ViewBag.Server = ParseConnectionString( ViewBag.ConnectionString, "Data Source" );
            ViewBag.Database = ParseConnectionString( ViewBag.ConnectionString, "Initial Catalog" );

            using ( var db = new SysDbContext( ViewBag.ConnectionString ) )
            {
                var objects = db.Set<SqlObject>().ToArray();

                var model = objects
                    .Select( o => new RadioButtonItem { Name = o.Name, Selected = false, ObjectId = o.Object_Id, CheckBoxItems = Enumerable.Empty<EF_Utility.Models.CheckBoxItem>() } )
                    .OrderBy( rb => rb.Name );

                return View( model );
            }
        }
    }
4

2 に答える 2

2

2 つの問題があります。

まず、ViewModel のコンストラクターで空のリストを作成していません。デフォルトのモデル バインダーは子オブジェクトをインスタンス化しないため、コンストラクターでインスタンス化する必要があります。

次に、ビューで foreach を使用すると、モデル バインダーが入力をリストにバインドするのに適切な名前が付けられません。

いくつかのオプションがあります。推奨される方法は、EditorTemplate を使用することです。~/Views/Shared フォルダーに EditorTemplates というフォルダーを作成し、その中に RadioButtonItem.cshtml というファイルを作成し、foreach 内のコードをそのファイルに配置して、Html.EditorFor(m => m.RadioButtonItems)

または、for ステートメントを使用し、以下のように項目をリストへのインデックスとして参照する必要があります。

@for(int i = 0; i < Model.RadioButtonItems.Count; i++)
{
    .....
    <label>
    @Html.RadioButtonFor(m => m.RadioButtonList[i].Selected, true) 
    @Html.RadioButtonFor(m => m.RadioButtonList[i].Selected, false)
    m.RadioButtonList[i].Name
    </label>
    ..... 
}

問題は、正しいワイヤ形式を作成していないことです。次の記事を参照してください。

http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

于 2012-10-04T14:35:13.727 に答える
0

これが私がやらなければならなくなったことです:

関連するModelクラスでポストバックを処理する新しいControllerメソッドを定義し、ビューでこれを使用してネストされた関連するチェックボックスを処理します。

    @Html.Raw(ViewBag.TextBoxes)

また、わかりやすくするために、クラスの名前を「RadioButtonItem」から「TableOrViewItem」に変更しました。これが私が追加したControllerメソッドです:

    [HttpPost]
    public ActionResult Connect( TableOrViewItem rbl )
    {
        /* TEST SESSION FIRST*/
        if ( Session["connstr"] == null )
            return RedirectToAction( "Index" );
        else
        {
            ViewBag.Message = "";
            ViewBag.ConnectionString = Server.UrlDecode( Session["connstr"].ToString() );
            ViewBag.Server = ParseConnectionString( ViewBag.ConnectionString, "Data Source" );
            ViewBag.Database = ParseConnectionString( ViewBag.ConnectionString, "Initial Catalog" );
            ViewBag.Selected = Request["name"] != null ? Request["name"].ToString() : "";
            ViewBag.ObjectID = Request["id"] != null ? Request["id"].ToString() : "";

            using ( var dbo = new SqlObjectContext( ViewBag.ConnectionString ) )
            {

                // obtain this item's objectid
                string CurrentObjectId = Request["id"].ToString();
                int CurrentID = StringToInt( CurrentObjectId );

                // populate Checkbox Area

                var rawColumns = dbo.Set<SqlColumn>()
                    .Where( column => column.ObjectId == CurrentID )
                    .OrderBy( o => o.ColumnId )
                    .ToList();

                string htmlColumns = string.Empty;

                foreach ( EF_Utility.Models.SqlColumn item in rawColumns )
                {
                    htmlColumns += "<input checked=\"checked\" id=\"RadioButtonViewModel_CheckBox" 
                        + item.ColumnId + "\" name=\"CheckBox_" + item.ColumnId 
                        + "\" type=\"checkbox\" value=\"" + item.Name + "\">" 
                        + item.Name + " <br>";
                }
                if(! string.IsNullOrEmpty(htmlColumns))
                {
                    htmlColumns += "<br /><center><input type=\"submit\" value=\"Generate\" name=\"btnGenerate\" id=\"btnGenerate\" /></center>";
                    htmlColumns += "<input type=\"hidden\" name=\"id\" value=\"" + CurrentObjectId + "\" />";
                    htmlColumns += "<input type=\"hidden\" name=\"name\" value=\"" + ViewBag.Selected + "\" />";
                }

                ViewBag.TextBoxes = htmlColumns;

                /*var ColumnItemList = columns
                    .Select( c => new ColumnItem { Name = c.Name, Selected = true, ObjectId = c.ObjectId } )
                    .Where( tvi => tvi.ObjectId == CurrentID );
                */

                // Check to see if the user wants the list generated

                if(Request["btnGenerate"] != null)
                {
                    string sNewLine = System.Environment.NewLine;
                    string htmlText = "[Table( \"" + ViewBag.Selected +"\" )]" + sNewLine +
                        "public class " + POCOFormated( ViewBag.Selected ) + sNewLine + "{";
                    string tempColumn = string.Empty;
                    string tempName = string.Empty;

                    foreach(string key in Request.Form)
                    {
                        if(!key.StartsWith("CheckBox_")) continue;

                        tempName = POCOFormated( Request.Form[key] );
                        htmlText = htmlText +
                            sNewLine + "\t" +
                            "public " + "...fieldtype..." + " " + tempName.Trim() + " { get; set; }" +
                            sNewLine; 
                    }                       
                    htmlText = htmlText + sNewLine + "}";

                    ViewBag.TextArea = htmlText;
                }

                var objects = dbo.Set<SqlObject>().ToArray();

                var model = objects
                    .Select( o => new TableOrViewItem { Name = o.Name, Selected = false, ObjectId = o.ObjectId } )
                    .OrderBy( rb => rb.Name );


                return View( model );
            }
        }
    }
于 2012-10-08T15:36:09.147 に答える