What would be the type of item in MVC4 WebGrid - asp.net-mvc-3

I am using webgrid to displat list of records.
My view is tightly coupled with IEnumerable.
#model IEnumerable<Models.SitesConfig.Configuration>
I am binding webgrid with Model.
var grid = new WebGrid(Model, rowsPerPage: 50);
I am trying to format a column using #helper method. #helper method taking a parametr of type Models.SitesConfig.Configuration.
When I try to load the view, I am getting invalid arguments error.
This is my view.
#model IEnumerable<Models.SitesConfig.SiteConfiguration>
#section Styles {
<link href="#Url.Content("~/Content/SatelliteSite.css")" rel="stylesheet" type="text/css" />
}
#{
ViewBag.Title = "List of Satellite Sites";
}
#helper FormatTemplateColors(Models.SitesConfig.SiteConfiguration item)
{
#String.Format(
"Border: {0} <br/>Link: {1} <br/>Text: {2}",
item.BorderColor != null ? item.BorderColor.Name : string.Empty,
item.LinkColor != null ? item.LinkColor.Name : string.Empty,
item.TextColor != null ? item.TextColor.Name : string.Empty)
}
#{
var grid = new WebGrid(Model, rowsPerPage: 50);
}
<div>
#grid.GetHtml(columns: grid.Columns(
grid.Column("Template",
style: "color-column-width",
format:(item) => #FormatTemplateColors(item)
)
)
</div>
Can somebody help me on this.

In the format lambda the item parameter is an instance of the WebGridRow class (in a form of dynamic) where the Value property holds the actual item.
So you need to write:
format:(item) => #FormatTemplateColors(item.Value)
SideNote if you wan't to output html you need to use the Html.Raw helper. So modify your helper to:
#helper FormatTemplateColors(Models.SitesConfig.SiteConfiguration item)
{
#Html.Raw(String.Format(...
}

Related

Change the background color of the first row in Helper WebGrid MVC without JQuery

I would like to change the background color of the first row in a WebHelper WebGrid for MVC without the use of JQuery.
Any Thoughts?
#model IEnumerable<MyViewModel>
#{
var indexedModel = Model.Select((item, index) => new { Element = item, Index = index });
var grid = new WebGrid(indexedModel);
}
#grid.GetHtml(
columns: grid.Columns(
grid.Column(
columnName: "item.MyProperty",
header: "Myproperty",
format:
#<text>
<div#Html.Raw(item.Index == 0 ? " class=\"firstRow\"" : "")>
#item.Element.MyProperty
</div>
</text>
)
)
)
and in your CSS:
.firstRow {
background-color: Red;
}
One suggestion could be in each columns's format parameter, use an if-else situation based on a distinct variable that will wrap the data in a span with a css. A bit cumbersome but should work.
For this reason some JQuery would potentially be easier.

MVC3 Helper DisplayFor Model

I've got a view that displays a list of items. Rather than display items in a grid, I'd like to display 4 items per page, each with an image and multiple properties, displayed in a unique layout.
So, I'd like a foreach to iterate through the items, and each item to get displayed in a div. I could put all the code in the loop, but I'd like to have a custom html helper extension to do this.
I came up with this,
public static MvcHtmlString DisplayViewerFor(this HtmlHelper helper, TestModel model, bool rightAligned = true) {
if (model == null) {
model = new TestModel();
}
var outterDiv = new TagBuilder("div");
outterDiv.AddCssClass(rightAligned ? "item-display-right" : "item-display");
var image = new TagBuilder("image");
image.Attributes.Add("src", "Item/GetImage/" + model.ItemName);
image.Attributes.Add("height", "150");
var editorLabel = new TagBuilder("div");
editorLabel.AddCssClass("editor-label");
//LOOKING TO ADD CODE LIKE THIS HERE
var labelContent= html.LabelFor({my model property here})
editorLabel.InnerHtml += labelContent;
//END OF ADD
return new MvcHtmlString(outterDiv.ToString(TagRenderMode.EndTag));
}
In my method above, I need to display a few more values, and I would like to use the Html.LabelFor and Html.DisplayFor helpers, but the methods aren't available and I'm not sure what to pass to them if they were.
I'm not sure if this is possible or not, but I thought I would ask.
EDIT
I'm trying to use the html.LabelFor. See my code where I have updated it above, adding to it these two lines.
var labelContent= html.LabelFor({my model property here})
editorLabel.InnerHtml += labelContent;
You can see the code above.
EDIT 2
Here is the planned use for this Helper with dummied down view.
#model TestItemDisplayList
#{
ViewBag.Title = "Items";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#foreach(var item in #model.Items){
#Html.DisplayViewerFor(item)
}
You can use the Html.DisplayFor method to render a DisplayTemplate. One of the over loads for the method is to specify a template to use. You can modify your page code to read:
Page:
#model TestItemDisplayList
#{ ViewBag.Title = "Items"; Layout = "~/Views/Shared/_Layout.cshtml"; }
#Html.DisplayFor(model => Model,"TestItemDisplayList")
Display Template for TestItemDisplayList
#model TestItemDisplayList
#* You could limit this loop to the first 4 items *#
#foreach(var item in model.Items){ #Html.DisplayFor(item => item) }
Display Template for TestModel
#model TestModel
<div class="item-display">
<img src="#Url.Action("GetImage", "Image", new { id = Model.ItemName})" height="150"/>
<div class="editor-label">#Html.LabelFor(model => model.PropertyHere)</div>
</div>
I assume that your URL for the image used the default route of {controller}/{action}/{id} so I used the Url.Action and specified your ID.
You could also get away witout using a DisplayTemplate for "TestItemDisplayList" and moving that code in to your page but I wasn't clear if you wanted to add logic in that to limit the number of pages.

#Html.DropDownList width

Q: How to set width for #Html.DropDownList (and not in css)?
#Html.DropDownList("ListId", String.Empty, new {style="width: 250px;"}) #* no go!*#
The second argument of the DropDownList helper must be an IEnumerable<SelectListItem>. You are passing a string (an empty one to be more precise). So in order to use this helper you will have to respect its signature:
#Html.DropDownList(
"ListId",
Enumerable.Empty<SelectListItem>(),
new { style = "width: 250px;" }
)
Obviously generating an empty dropdown list is of little use. You probably have a view model (you should by the way) that you want to use to bind to:
#Html.DropDownList(
"ListId",
Model.MyList,
new { style = "width: 250px;" }
)
and of course because you have a view model you should prefer to use the DropDownListFor helper:
#Html.DropDownListFor(
x => x.ListId,
Model.MyList,
new { style = "width: 250px;" }
)
and finally to avoid cluttering your HTML with styles you should use an external CSS:
#Html.DropDownListFor(
x => x.ListId,
Model.MyList,
new { #class = "mycombo" }
)
where in your external CSS you would define the .mycombo rule:
.mycombo {
width: 250px;
}
Now you have what I consider a proper code.
You should use the View Model approach. However the lazy way out is just to give the 2nd parameter a null.
#Html.DropDownList("ListId", null, new {style="width: 250px;"})
#Html.DropDownListFor(model => model.Test,
new SelectList(new List<YourNamespace.Modelname>(), "Id", "Name"),
null, new { #id = "ddlTest", #style="width: 250px;" })
There is a jquery technique that allows you to set the width without having to deal with the #Html.DropDownList constructor.
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$("#ListId").width(300);
});
</script>

How to get my Action method to give me back my model from web grid with checkboxes

I have a strongly typed view which is uses an IEnumerable as its model.
There's a bool property on the model which I'm rendering in a MVC WebGrid in a checkbox which the user can then check or uncheck.
On submit it gets to my action method but how do I get the checked checkboxes?
If I look at the Request.Params, I see all the checked checkboxes coming back as parameters. Is there any easy way for the DefaultModelBinder to convert these back into my IEnumerable, or do I have to do this by hand?
Here's my View so far:
#model IEnumerable<XXX.XXXItemDto>
<div id="items">
#using (Ajax.BeginForm("SaveEvents", "MyController", new AjaxOptions { UpdateTargetId = "items" }))
{
var grid = new WebGrid(Model, canPage: false, canSort: false);
#grid.GetHtml(columns: grid.Columns(
grid.Column("itemDescription", header: "Event"),
grid.Column("acknowledged", format: #<text><input name="Acknowledged_#(item.staffItemOid)" type="checkbox" value="#item.staffItemOid" #(item.acknowledged ? "Checked" : null)/> </text>, header: "Acknowledged")
))
#Html.SubmitButton("Save")
}
</div>

MVC3 Partial View - Is it better Ajax.BeginForm or Ajax.ActionLink?

I have a Partial View with two opposite ActionLinks inside:
<div id="divStatus>
#if (IsAuthenticated)
Html.ActionLink("Say Bye", "ProcBye", "Account")
else
Html.ActionLink("Say Hi", "ProcHi", "Account")
</div>
Each Action link calls a different method on the Controller.
I hear I should use Ajax.BeginForm but I'm still NOT clear how to put this?
My understanding is that I need a <div id="divStatus"> to display the result, but in my case ...the result is the Partial View itself.
QUESTION: How do I ensure make it so the Controller just refreshes the calling Partial View??
Shall I just add a div outside the PV?
Shall I add the div inside the PV surrounding the '#if (IsAuthenticate)' call?
Is it better to use Ajax.BeginForm or Ajax.ActionLink in this case?
CODE: What should the code for the Controller look like?
public ActionResult ProcBye()
{
// do something on the server
// set IsAuthenticated = false;
return PartialView("_myPV");
}
There is NO Validation Involved, NO "external" div that needs to be populated, just a simple refresh of the PV independently from what page the PV is located.
Any help will be truly appreciated !!!
Personally I wouldn't use neither. I would use a separate javascript file in which I would AJAXify the link:
$(function() {
$('.mylink').click(function() {
$('#resultdiv').load(this.href);
return false;
});
});
where resultdiv will be a div which will be update with the partial result returned from the controller action:
<div id="resultdiv"></div>
You just need to put the mylink class:
#if (IsAuthenticated)
{
#Html.ActionLink("Say Bye", "ProcBye", "Account", null, new { #class = "mylink" })
}
else
{
#Html.ActionLink("Say Hi", "ProcHi", "Account", null, new { #class = "mylink" })
}
You could also use Ajax.ActionLink if you wanted to:
#if (IsAuthenticated)
{
#Ajax.ActionLink("Say Bye", "ProcBye", "Account", new AjaxOptions { UpdateTargetId = "resultdiv" })
}
else
{
#Ajax.ActionLink("Say Hi", "ProcHi", "Account", new AjaxOptions { UpdateTargetId = "resultdiv" })
}
Just don't forget to include the jquery unobtrusive ajax script in this case:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>

Resources