我有一个模型定义,根据IEnumerable为我提供一个带有RadioButtons列表的视图。
在该模型中,我想显示一个复选框列表,这些复选框将根据所选项目而有所不同。最后,一旦用户从可用的复选框中选择,将在同一视图中存在Textarea,其中一些动态文本基于所选的CheckBox。我们最终应该得到的是每层次表。
布局是这样的,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应该是相当简单的。
EDIT **所以我需要将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 );
}
}
}
答案 0 :(得分: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>
.....
}
问题是您没有创建正确的有线格式。请参阅以下文章:
答案 1 :(得分:0)
以下是我最终需要做的事情:
使用相关的Model类定义一个新的Controller方法来处理回发,并在View中处理嵌套的相关Checkbox:
@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 );
}
}
}