MVC WebGrid Dynamic Content - c#

What I am trying to achieve is hard to explain, so please let me know if I can provide more information. I have a feeling that I am trying to use WebGrids beyond their means, so if anyone has any open source alternatives that would do what I am trying, that would also be helpful.
I need to build a WebGrid from the ground up, because the content returned to it (columns and values) changes depending on other criteria on my form. I have this working in a few simple lines of code in a Table, but I wanted to use WebGrid for the styling, sorting and paging.
#model DocumentSearchViewModel
#if ((this.Model != null) && (this.Model.SearchResults != null) && (this.Model.SearchResults.Count() > 0))
{
<table>
<thead>
<tr>
<th>Document</th>
#foreach (var metadata in this.Model.SearchResults.Metadata)
{
<th>
#metadata.InstanceFieldName
</th>
}
</tr>
</thead>
<tbody>
#foreach (var document in this.Model.SearchResults)
{
<tr>
<td>
#Html.ActionLink(document.Id.ToString(), "Details", new { id = document.Id })
</td>
#foreach (var metadata in document.Metadata)
{
<td>
#metadata.Value
</td>
}
</tr>
}
</tbody>
</table>
}
So to explain the model structure, The SearchResults has an IEnumerable<MetadataModel>, and this MetadataModel has properties of InstanceFieldName and Value. When a search is performed, every result will always have the same number of Metadata, and the same InstanceFieldNames, but different values, however a quick change of a field on the form, and a new search could return a new set of results (Again with the same set of Metadata as each other, but different to the first set of results)
The columns of the grid correspond to the Metadata InstanceFieldName, and the content the Value.
So I have made my best attempt using WebGrid, but the best I can get is a grid with the right column headers, and the right number of rows, the columns have the right data, but each row is the same (copied from the last row).
#{
var grid = new WebGrid(canPage: true, canSort: true, rowsPerPage: Model.PageSize, sortFieldName: Model.Sort, sortDirectionFieldName: Model.SortDir);
grid.Bind(Model.SearchResults, rowCount: Model.DocumentCount);
List<WebGridColumn> cols = new List<WebGridColumn>();
foreach(var metadata in Model.SearchResults.Select(r => r.Metadata).FirstOrDefault())
{
var col = new WebGridColumn();
col.ColumnName = metadata.InstanceFieldName;
col.Header = metadata.InstanceFieldHeader;
col.Style = "gridRow";
col.CanSort = true;
cols.Add(col);
}
foreach (var result in Model.SearchResults)
{
foreach (var col in cols)
{
var metadataValue = result.Metadata.Single(m => m.InstanceFieldName == col.ColumnName).Value;
col.Format = (item) => #Html.Raw("<text>" + metadataValue + "</text>");
}
}
}
#if ((this.Model != null) && (this.Model.SearchResults != null) && (this.Model.SearchResults.Count() > 0))
{
#grid.GetHtml(htmlAttributes: new { id = "documentGrid" }, rowStyle: "gridRow", alternatingRowStyle: "gridRowAlt", columns: cols)
}
What I'm trying to work out is how and if possible to generate the columns first, and then populate the rows into these columns.
Any help is really appreciated, thanks, Mark

You are feeding the rows with the same value, you should change the Format:
col.Format = (item) => #Html.Raw(item.metadataValue);

Related

Use only part of a DB when iterating ASP.net - iterating through the whole DB slows it way down

I'm a brand new programmer and am stuck - hoping for advice.
I have a program through ASP.net. It works great until the DB gets about 100 entries and then it gets really slow.
I know the reason but don't know how to fix it.
The program allows employees of a large 911 dispatch center to sign up for breaks, lunches and restroom breaks from their consoles. They select their names and position from dropdowns. It adds the info to a DB when they click submit. The program then iterates through the DB to find the active breaks / lunches / restroom breaks to find the active ones and displays them in a table.
It's important that the table update quickly when someone goes on a list so everyone from all consoles knows when someone adds to that table. So I have the program iterating through the db every 5 seconds to update who's on what list. It's happy with less than 100 entries but it doesn't do well with more - which makes sense - that's a lot to iterate through in such a little time frame.
I had two possible ideas but I don't know how to make them work and the Google isn't helping much.
One thought was just to import data from just the past two days and have it just iterate through that. Without iterating like I have it now, I'm not sure how to get it to do that.
Another thought I had was to save everything into a list at the same time it saves to the DB so it iterates just through memory and not a DB. I don't know how to store multiple fields into that list, though. Maybe a dictionary? I don't know. I don't know how practical that is.
Here's some of the code:
Controller:
[System.Web.Http.HttpPost]
public ActionResult CreateLunch(Lunch lunch)
{
try
{
lunch.TimeEntered = DateTime.Now;
db.Lunches.Add(lunch);
db.SaveChanges();
var breaksList = db.Breaks.ToList();
foreach (var item in breaksList)
{
Break mdl = new Break();
mdl.BreakID = item.BreakID;
mdl.Employee = item.Employee;
mdl.TimeEntered = item.TimeEntered;
mdl.TimeCleared = item.TimeCleared;
mdl.PositionID = item.PositionID;
mdl.EmpSent = item.EmpSent;
if (db.Breaks != null)
{
db.Breaks.Add(mdl);
}
db.Breaks.Add(mdl);
}
var employee = db.Employees.ToList();
foreach (var item in employee)
{
Employee mdl = new Employee();
mdl.EmployeeID = item.EmployeeID;
mdl.FirstName = item.FirstName;
mdl.LastName = item.LastName;
mdl.NotActive = item.NotActive;
mdl.Force = item.Force;
mdl.DisplayName = item.DisplayName;
if (db.Employees != null)
{
db.Employees.Add(mdl);
}
}
var dthmodel = db.Dths.ToList();
foreach (var item in dthmodel)
{
Dth mdl = new Dth();
mdl.DthID = item.DthID;
mdl.Employee = item.Employee;
mdl.TimeCleared = item.TimeCleared;
mdl.TimeEntered = item.TimeEntered;
mdl.PositionID = item.PositionID;
mdl.EmpSent = item.EmpSent;
if (db.Dths != null)
{
db.Dths.Add(mdl);
}
}
var lunchModel = db.Lunches.OrderBy(x => x.LunchTime);
foreach (var item in lunchModel)
{
Lunch mdl = new Lunch();
mdl.Employee = item.Employee;
mdl.LunchID = item.LunchID;
mdl.PositionID = item.PositionID;
mdl.LunchTime = item.LunchTime;
mdl.LongerLunch = item.LongerLunch;
mdl.Double = item.Double;
mdl.TimeEntered = item.TimeEntered;
mdl.EmpSent = item.EmpSent;
mdl.TimeCleared = item.TimeCleared;
if (db.Lunches != null)
{
db.Lunches.Add(mdl);
}
}
var positionModel = db.Positions.ToList();
foreach (var item in positionModel)
{
Position mdl = new Position();
mdl.PositionID = item.PositionID;
mdl.PositionName = item.PositionName;
if (db.Positions != null)
{
db.Positions.Add(mdl);
}
}
var date = DateTime.Now;
var dateOffset = DateTime.Now.AddDays(-1);
ViewBag.EmployeesNames = db.Employees.Where(x => x.NotActive == false).OrderBy(x => x.DisplayName).ToList();
ViewBag.PositionNames = db.Positions.ToList();
ViewBag.LunchTimes = db.Lunches.Where(x => x.TimeEntered <= date && x.TimeEntered >= dateOffset).OrderBy(x => x.LunchTime).ToList();
ViewBag.positionOrdered = db.Positions.OrderBy(m => m.PositionName).ToList();
ViewBag.Dths = db.Dths.Where(x => x.TimeEntered <= date && x.TimeEntered >= dateOffset).ToList();
ViewBag.Breaks = db.Breaks.Where(x => x.TimeEntered <= date && x.TimeEntered >= dateOffset).ToList();
ViewBag.Lunches = db.Lunches.Where(x => x.TimeEntered <= date && x.TimeEntered >= dateOffset).ToList();
ViewBag.breakOffFloor = db.Breaks.Where(x => x.EmpSent == true && x.TimeCleared == null && (x.TimeEntered <= date && x.TimeEntered >= dateOffset)).ToList();
ViewBag.dthOffFloor = db.Dths.Where(x => x.EmpSent == true && x.TimeCleared == null && (x.TimeEntered <= date && x.TimeEntered >= dateOffset)).ToList();
ViewBag.lunchOffFloor = db.Lunches.Where(x => x.EmpSent == true && x.TimeCleared == null && (x.TimeEntered <= date && x.TimeEntered >= dateOffset)).ToList();
string partialHtml = Common.RenderRazorViewToString(ControllerContext, "~/Views/Home/_DropDowns.cshtml");
return Json(new { success = true, html = partialHtml }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return Json(new { success = false });
}
}
Index:
var employee = ViewBag.EmployeesNames;
var positionNames = ViewBag.PositionNames;
var modelOrdered = ViewBag.LunchTimes;
var positionOrdered = ViewBag.positionOrdered;
var breakOffFloor = ViewBag.breakOffFloor;
var dthOffFloor = ViewBag.dthOffFloor;
var lunchOffFloor = ViewBag.lunchOffFloor;
<div class="card" id="Dropdowns" style="width: 12.5em; margin-left: .5em; position:absolute">
<div class="card-body" id="refresh-card" style="margin-right:3em; margin-left:-.5em">
<h5 class="card-title " style="text-align:center; display:inline-block; margin-left:3em">DTH <img src="~/Content/Images/question.jpg" height="15" width="15"
data-toggle="popover" title="#DTHquestion"/></h5>
<table class="table-bordered" style="width:10em;">
#*populate the table with only those breaks that lack a TimeCleared value*#
#if (ViewBag.Dths != null)
{
foreach (var item in ViewBag.Dths)
{
if (item.TimeCleared == null)
{
if (item.TimeEntered.AddMinutes(1) > DateTime.Now)
{
if (item.EmpSent == false)
{
<tr>
#*Make each name clickable to set a TimeCleared datetime.Now time*#
<td class="listTime">
<input type="hidden" class="hiddenDthID" value="#item.DthID" />
#item.Employee.DisplayName
</td>
<td class="listTime" style="width:2.5em">
#item.Position.PositionName
</td>
<td class="listTime" style="width:1.5em; text-align:center">
<input type="checkbox" class="dthSent" value="#item.EmpSent" />
</td>
</tr>
}
if (item.EmpSent == true)
{
<tr>
#*Make each name clickable to set a TimeCleared datetime.Now time*#
<td class="empSentGreen">
<input type="hidden" class="hiddenDthID" value="#item.DthID" />
#item.Employee.DisplayName
</td>
<td class="empSentGreen" style="width:2.5em">
#item.Position.PositionName
</td>
<td class="empSentGreen" style="width:1.5em; text-align:center">
<img height="13" width="13" src="~/Content/Images/disabledcheck.jpg" />
</td>
</tr>
}
}
else
{
if (item.EmpSent == false)
{
<tr>
#*Make each name clickable to set a TimeCleared datetime.Now time*#
<td class="DthIdNumber">
<input type="hidden" class="hiddenDthID" value="#item.DthID" />
#item.Employee.DisplayName
</td>
<td class="DthIdNumber" style="width:2.5em">
#item.Position.PositionName
</td>
<td class="DthIdNumber" style="width:1.5em; text-align:center">
<input type="checkbox" class="dthSent" value="#item.EmpSent" />
</td>
</tr>
}
if (item.EmpSent == true)
{
<tr>
#*Make each name clickable to set a TimeCleared datetime.Now time*#
<td class="DthIdNumber" style="background-color:lightgreen">
<input type="hidden" class="hiddenDthID" value="#item.DthID" />
#item.Employee.DisplayName
</td>
<td class="DthIdNumber" style="width:2.5em;background-color:lightgreen">
#item.Position.PositionName
</td>
<td class="DthIdNumber" style="width:1.5em; background-color:lightgreen;text-align:center">
<img height="13" width="13" src="~/Content/Images/disabledcheck.jpg" />
</td>
</tr>
}
}
}
}
}
</table>
Thank you!
Yes, there is a scope of optimization in the code shared by you. But that won't solve your underlying problem.
The real problem is not the code but bad database design and poor approach towards the problem.
I would suggest you to keep only one table for the lunch details. say (LUNCH_DETAILS)
Based on above shared problem, the structure would look something like this:
ID (Primary Key) PostionId EmployeeId TimeEntered TimeCleares IsAvailable ...others
101 10 1001 12:30 01:00 Y .........
102 11 1002 12:40 N .........
Now any time any employee visits the canteen to have their lunch, you would only do one insert in above table and based on IsAvailable column you can tell if a postion (with PostionId ) is currently available or not.
With this approach there will only be one insert operation and no need to iterate to any data.

Get a determined value inside a dropdowList

I'm doing a page to edit a product,the product have some characteristics,i'm using a getAll to recover all of the characteristics.
model.Listcharacteristics= v_ProdutoCharacteristicsMetodos.GetAll(EmpresaId)
.Select(x => new ProdutoCharacteristicsModel()
{
Apagado = x.Apagado,
DeAte = x.DeAte,
DepartamentoId = x.DepartamentoId,
Descricao = x.Descricao,
Description = x.Description,
Fator = x.Fator,
Keywords = x.Keywords,
MostrarHome = x.MostrarHome,
NCM = x.NCM,
Ordem = x.Ordem,
PessoaId = x.PessoaId,
ProdutoFamiliaId = x.ProdutoFamiliaId,
UrlImagem = x.UrlImagem
})
.ToList();
But i have a method that can get the product characteristic by the product ID,so in the edit page,i need to show the currently characteristic instead of the default value,how i can select which value show first select in the dropDowList?
In the BLL i created this.
model.Produto.ProdutoFamilia = v_ProdutoFamiliaMetodos.GetById(produtoempresa.ProdutoFamiliaId).Descricao;
I'm passing produtoempresa (The product)and ProdutoFamiliaId is the caractheristic ID,i'm getting a string with the name of the characteristic,this name its what i have to show the default value.
The html is this.
<tr>
<td>
#if (this.Model.ListFamilia != null && (this.Model.ListFamilia.Count > 0))
{
for (int i = 0; i < Model.ListFamilia.Count; i++)
{
#Html.HiddenFor(model => model.ListFamilia[i].ProdutoFamiliaId)
#Html.HiddenFor(model => model.ListFamilia[i].Descricao)
}
}
#Html.DisplayNameFor(model => model.Produto.ProdutoFamiliaId)*
</td>
<td>
#Html.DropDownListFor(model => model.Produto.ProdutoFamiliaId, new SelectList(Model.ListFamilia, "ProdutoFamiliaId", "Descricao", Model.Produto.ProdutoFamiliaId), String.Empty)
</td>
</tr>
In the dropdowList the default value showing must be the model.Produto.ProdutoFamilia.
You usually render the dropdown box and set the selected value in the html. This is done with the
<select name="hall" id="hall" value="3">
<option selected="selected">1</option>
<option>2</option>
<option>3</option>
</select>
This will have the first option selected in your dropdown list. From your method that can get the product characteristic you should be able to calculate which option you want to append
selected="selected"
Hope this helps

Get ID of control from View into Controller

In my MVC application I have a view where I will display different data from a SQL table. This will generate different amount of drop down lists and text boxes, depending on what is passed in from the Model.
My issue is if I want to then use that data I can't seem to figure out how I can relate control X to object Y in SQL. For example, if I have 2 textboxes that I want to do an update on, then when the Post happens in my application the FormCollection parameter will let me see the Value of the objects, but not their control name or any form of identifying factor.
I could set the Value to a combination of the entered value + a name, then split this, but it seems very much like a lazy workaround.
I've tried to assign an ID to each, for example:
#foreach (DataObject item in Model.AllDataObjects)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Data)
</td>
<td>
#if (item.Rule.Contains("Yes;No"))
{
#Html.DropDownListFor(model => item.Value, new List<SelectListItem>
{
new SelectListItem {Text="Yes", Value="Yes"},
new SelectListItem {Text="No", Value="No" }
}, new { #id = item.ObjectId });
}
else
{
#Html.TextAreaFor(model => item.Value, new { style = "width: 400px;", #rows = 5, #id = item.ObjectId })
}
</td>
</tr>
}
Edit: The following is my Post ActionResult method in the Controller, albeit it isn't complete as I can't figure out how to get an ID for the control from the FormCollection
[HttpPost]
[ValidateInput(false)]
public ActionResult UpdateData(FormCollection collection, int objectId=0)
{
try
{
int propertyTypeId = 0;
string propertyValue = string.Empty;
// Get all the control values from the collection
string[] allValues = new string[] { };
IValueProvider valueProvider = collection.ToValueProvider();
foreach(string key in collection.Keys)
{
ValueProviderResult result = valueProvider.GetValue(key);
allValues = result.RawValue as string[];
}
ObjectData objectData = _execution.GetObjectDetails(0);
UpdateDataResponse result = _execution.UpdateData(0, objectId,
objectValue, UserName);
return RedirectToAction("Details",
new { ObjectId = objectData.ObjectId, error = result.ErrorMessage });
}
catch (Exception ex)
{
// My exception handling here
}
}
So I can see in the mark-up that the controls are assigned the object ID as their own ID, but how can I get this back? When I check FormCollection I only see the values for each control, but no way of identifying which is which.
Edit: I'm using MVC version 4.
A form only submits the values of its successful controls (as name/value pairs based on the controls name and value attributes) so if you do not generate a control for the ObjectId properties, they will not be submitted.
However, you current use of foreach loop will not allow you to obtain any meaning information from the data which is posted because all your names are identical and there is no way to reliable match up which value belongs to which item in the collection. Instead use a for loop or EditorTemplate in the view and bind to your model, rather than using FormCollection.
The view should be
#for (int i = 0; i < Model.AllDataObjects.Count; i++)
{
<tr>
<td>#Html.DisplayFor(m => m.AllDataObjects[i].Name)</td>
<td>#Html.DisplayFor(m => m.AllDataObjects[i].Data)</td>
<td>
#Html.HiddenFor(m => m.AllDataObjects[i].ObjectId)
#if (Model.AllDataObjects[i].Rule.Contains("Yes;No"))
{
#Html.DropDownListFor(m => m.AllDataObjects[i].Value, new SelectList(new string[]{ "Yes", "No" }));
}
else
{
#Html.TextAreaFor(m => m.AllDataObjects[i].Value, new { style = "width: 400px;", #rows = 5 })
}
</td>
</tr>
}
And assuming the model in the view is #model MyModel, change the POST method to
[HttpPost]
[ValidateInput(false)]
public ActionResult UpdateData(MyModel model)
and the value of model.AllDataObjects will contain a collection with its ObjectId and Value properties correctly bound.
For more information on why using a foreach loop will not work, refer to this answer.

TwitterBootStrapMVC Dropdownlist Selected Value

I can't get the selected values from the following dropdownlist, here how I generate the list:
In the repository:
public IQueryable<OhaType> GetAllOhaTypes ()
{ return db.OhaType.OrderBy(d => d.Name); }
In the controller:
....
var OhTypes = _medicationRepository.GetAllOhaTypes();
ViewBag.OhTypes = new SelectList(OhTypes, "OhaTypeId", "Name");
.....
In the View:
#foreach (var item in this.Model.OhaMedication)
{
<tr>
<td>
#(Html.Bootstrap().DropDownList("OhaTypeId", (SelectList)ViewBag.OhTypes)
.HtmlAttributes(new
{
Name ="OhaTypeId",
style = "width: 300px;"
}).Size(InputSize.Small)
.Class("form-group input-sm").Id("OhaTypeId")
.ShowValidationMessage(true))
</td>
.....
I get the first item of the list displayed not the correct value. I get the correct values in other fields from the table.
I also tried "#HTML.DropdownList(...)", same issue.
Would appreciate your suggestions.

C# MVC3 Razor alternating items in a #foreach list?

In MVC3, how do you create alternating row colors on a #foreach list when using the Razor view engine?
#foreach (var item in Model) {
<tr>
<td>#item.DisplayName</td>
<td>#item.Currency</td>
<td>#String.Format("{0:dd/MM/yyyy}", item.CreatedOn)</td>
<td>#String.Format("{0:g}", item.CreatedBy)</td>
<td>#Html.ActionLink("Edit", "Edit", new { id = item.Id })</td>
</tr>
}
Assuming you would rather not use CSS (i.e. :nth-child(odd)) you can either:
use a normal for loop:
#for (int i = 0; i < Model.Count; i++)
{
...
}
use .Select:
#foreach (var item in Model.Select((x, i) => new { Data = x, Index = i }))
{
...
}
Either way, you'd have access to the current index and could then use i % 2 == 1 as the condition for your background-color. Something like:
<tr style="background-color:#(i % 2 == 1 ? "red" : "white")">...</tr>
This is what CSS is for (changing style rather than content). Save the server the effort: Do it on the client.
Since you're using Razor, you can use JQuery. Here's how I do it in my projects:
$(document).ready(function () {
$("table > tbody tr:odd").css("background-color", "#F7F7F7");
}
With ASP.NET MVC 3 and the new #helper syntax, there is a neater way to handle this.
First add this #helper method:
#helper AlternateBackground(string color) {
if (ViewBag.count == null) { ViewBag.count = 0; }
<text>style="background-color:#(ViewBag.count % 2 == 1 ? color : "none")"</text>
ViewBag.count++;
}
Then just add the call to the helper in your <TR> element
#foreach (var item in Model) {
<tr #AlternateBackground("Red")>
<td>#item.DisplayName</td>
<td>#item.Currency</td>
<td>#String.Format("{0:dd/MM/yyyy}", item.CreatedOn)</td>
<td>#String.Format("{0:g}", item.CreatedBy)</td>
<td>#Html.ActionLink("Edit", "Edit", new { id = item.Id })</td>
</tr>
}
You could always do it in pure css using:
TABLE.test tr:nth-child(even)
{
background-color: #EFEFEF;
}
How about something like this?
#for (int i = 0; i < Model.length; i++) {
<tr #(i % 2 != 0 ? class="odd" : "")>
<td>#Model[i].DisplayName</td>
<td>#Model[i].Currency</td>
<td>#String.Format("{0:dd/MM/yyyy}", Model[i].CreatedOn)</td>
<td>#String.Format("{0:g}", Model[i].CreatedBy)</td>
<td>#Html.ActionLink("Edit", "Edit", new { id = Model[i].Id })</td>
</tr>
#{
int i = 0;
foreach (Account acct in Model)
{
<div class="row #(i%2==0?"even":"odd")">
#acct.name
</div>
i++;
}
}
Original: http://15daysofjquery.com/table-striping-made-easy/5/
Author: Jack Born
jQuery Zebra_Striping_Made_Easy
=============== Java script ===================
$(document).ready(function () {
$('.stripeMe tr:even').addClass('alt');
$('.stripeMe tr').hover(
function () {
$(this).addClass("highlight");
},
function () {
$(this).removeClass("highlight");
});
});
================= css =================
tr.alt td {
background-color : #F7F7F7;
}
tr.highlight td {
background-color : #bcd4ec;
}
=============== HTML ===============
<table class="stripeMe">
There isn't much documentation on it, but the Loop Helper (http://nuget.org/Packages/Packages/Details/Loop-Helper-for-WebMatrix-0-1) gives you support for detecting Even/Odd/etc. items.
What you can do is to set a variable odd outside of the foreach()
#{
var odd = false;
}
And then, inside your foreach loop, you'd change the value of it and then use it in an if condition to set the alternating classes.
#foreach (var item in Model) {
odd = !odd;
<tr class="#(odd ? "odd" : "even")">
<td>#item.DisplayName</td>
<td>#item.Currency</td>
<td>#String.Format("{0:dd/MM/yyyy}", item.CreatedOn)</td>
<td>#String.Format("{0:g}", item.CreatedBy)</td>
<td>#Html.ActionLink("Edit", "Edit", new { id = item.Id })</td>
</tr>
}
An old post, but none of the answers covered this approach, so I will.
Since you are using MVC Razor utilizing the #helper function is the simplest, cleanest and best approach.
In the App_Code folder of your project add new item or modify your existing CustomeHelpers.cshtml file with the following code:
#helper AlternateBackground(string color, Int32 iViewBagCount) {
if (iViewBagCount == null) { iViewBagCount = 0; }
<text>style="background-color:#(iViewBagCount % 2 == 1 ? color : "none")"</text>
iViewBagCount++;
}
Then on your view your foreach loop would look like this:
#foreach (var item in Model) {
<tr #CustomHelpers.AlternateBackground("#ECEDEE", Model.Count())>
<td>#item.DisplayName</td>
<td>#item.Currency</td>
<td>#String.Format("{0:dd/MM/yyyy}", item.CreatedOn)</td>
<td>#String.Format("{0:g}", item.CreatedBy)</td>
<td>#Html.ActionLink("Edit", "Edit", new { id = item.Id })</td>
</tr>
}
You can pass a color identifier like "#ECEDEE" or the named color "Blue".
This way you only have to add the #Helper function once and it propagates throughout your application and it can be called on each view as needed by referencing the #CustomHelpers function.
what about using the jQuery DataTable plugin. i used it on an MVC2 application i developed.
http://www.datatables.net/
A solution i use to support IE8 (corporate browser, not by choice) was to combine the_lotus's solution with a jquery solution
Since IE8 doesnt support nth-child() use this css
.tableclass tr.even{
background:#E6EDF5;
}
And use jQuery to do this:
$(document).ready(function() {
$(".table tr:nth-child(even)").addClass("even");
});
You could let the framework decide how best to render it, presumably using a bit of browser detection logic and whatever other goodness it has built-in, something like the following, and get on with your life.
:-)
My point being that with this approach the WebGrid will control the alternating grid colors using the best technology it can (best that it is designed to use, at least) for the detected browser. It might not use "nth" CSS syntax, but that might not work for all of your intended audience, anyway, so you'd have to detect the browser and emit different content on your own. Of course everybody should be using a CSS 3.x-compliant browser by now, but mileage varies.
#myWebGrid.GetHtml
(
tableStyle: "some-style",
headerStyle: "some-head-style",
alternatingRowStyle: "some-fancy-alt-row-style",
etc ...
)
The System.Web.Helpers.WebGrid's GetHtml method signature looks like this here:
public IHtmlString GetHtml
(
string tableStyle = null,
string headerStyle = null,
string footerStyle = null,
string rowStyle = null,
string alternatingRowStyle = null,
string selectedRowStyle = null,
string caption = null,
bool displayHeader = true,
bool fillEmptyRows = false,
string emptyRowCellValue = null,
IEnumerable<WebGridColumn> columns = null,
IEnumerable<string> exclusions = null,
WebGridPagerModes mode = WebGridPagerModes.Numeric | WebGridPagerModes.NextPrevious,
string firstText = null,
string previousText = null,
string nextText = null,
string lastText = null,
int numericLinksCount = 5,
object htmlAttributes = null
);
#helper Prop(List prop)
{
foreach (var p in prop)
{
p
}
}
format: #Prop(#item.Prop)

Categories

Resources