1

我定义了一个模型,它可以根据 IEnumerable 为我提供一个带有 RadioButtons 列表的视图。

在该模型中,我想显示一个复选框列表,这些复选框将根据所选项目而有所不同。最后,一旦用户从可用的复选框中进行选择,同一视图中将出现一个 Textarea,其中包含一些基于所选复选框的动态文本。我们最终应该得到一个 Table-per-hierarchy。

布局使得 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 应该相当简单。

编辑**所以我需要将 RadioButtonItem 绑定到视图,如下所示,除了我的 CheckBoxList 不会是空集。

    //
    // 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

你有两个问题。

首先,您不会在 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

这是我最终需要做的事情:

定义一个新的控制器方法来处理相关模型类的回发,并在视图中处理嵌套的相关复选框:

    @Html.Raw(ViewBag.TextBoxes)

为了清楚起见,我还将类从“RadioButtonItem”重命名为“TableOrViewItem”。这是我添加的控制器方法:

    [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 回答