3 level of lists in nested view - c#

I have these tables Pages, PageVersions and ElementsOnPageVersions.
I want to show this on a page all at once, in a collapsible kind of view.
Like this:
Page 1
Version 1
Version 2
Version 3
Version 4
Element 1
Element 2
Element 3
Page 2
Version 1
Version 2
Version 3
Version 4
Element 1
Element 2
Page 3
Version 1
Element 1
Page 4
Version 1
Element 1
I'm uncertain on what the best way to retrieve the data and easily show it in the collapsaple layout is.
I would do something like this:
Get all items, all at once. "select * from ElementsOnPageVersion e inner join PageVersions v on e.PageVersion = v.id inner join Pages p on v.PageId = p.id"
Iterate through all, and build hierachical structure of sorted list to look like the collapsaple layout. PageLists[PagesObject], PagesObject has a sorted list of PageVersionObjects, which has a sorted list of ElementObjects.
Iterate through the final PagesList list Building the page. Inside this iterating through pageversionslist showing versions for the page, and Again inside every version iterating through elementslist.
This would be the way I would do it, at this moment. But it seems too heavy, and a lot of iterating.
What would be the best way to do this?

I'd think about projecting your three different items to a single self-referencing list. Each item would need an Id, Description, and ParentId. I'd make a view model for this purpose.
public class TreeItem {
public int Id {get; set;}
public string Description {get; set;}
public int ParentId {get; set;}
}
That would allow for you to leverage either an asp:TreeView in webforms or whatever flavor of jQuery tree / treeview if you're using MVC.

i actually built something that does something very similar. i can give you the HTML source to mine but i'd need to modify the .NET code to remove company specific, proprietary information before releasing that publicly (plus convert it to C#).
unfortunately for me to modify mine to your needs, it'd be almost up to one month before i'd be able to get around to it (due to a busy week before we take a 2 week vacation). but you can look at my HTML and see what you can reuse from it. from what i understand of your request, you'd be scratching about half of my JavaScript and its functionality. but if i were in your shoes, i'd appreciate this code to use as a starter and scrap what i didn't want and maybe add something. or you may just think my code is trash and not use it at all. ;P
so here's my HTML & JavaScript so you can run with it. It does handle the collapsing and expanding of nodes tho using ul and ol lists.
<!DOCTYPE HTML>
<html>
<head><title>Oz-Med-Hist-VB</title>
<meta charset='utf-8' />
<meta http-equiv='X-UA-Compatible' content='IE=EmulateIE8' />
<style type='text/css'>
body { background: #CCC; margin-left: 1.5em; }
li { list-style-type: none; text-indent: -38px; }
.emptyGrayBox8 {
background-color: #bbb; /* checked and unchecked background color */
border: 1px solid #777; /* checked and unchecked border width & style & color */
padding: 5.5px; display: inline-block; position: relative; margin: 0 3px; margin-top: 3px;
}
.checkInsideGrayBox:after {
content: 'X';
font-size: 13px;
position: absolute;
top: -2px;
left: 1.5px;
color: #555;
}
.checkInsideGrayBoxInsideLI:after {
content: 'X';
font-size: 13px;
position: absolute;
top: -2px;
left: 39.5px;
color: #555;
}
</style>
<script>
if (navigator.userAgent.indexOf('MSIE 8.') < 0)
{
document.write(
' <style>\n' +
' .checkInsideGrayBox { left: 0.5px; }\n' +
' .checkInsideGrayBoxInsideLI:after { left: 38.5px; }\n' +
' </style>');
}
var dta =
{ 'checkedSubNodeCount--1' : 0
, 'checkedSubNodeCount--19' : 0
, 'checkedSubNodeCount--19-a': 0
, 'checkedSubNodeCount--19-b': 0
, 'checkedSubNodeCount--19-c': 0
, 'checkedSubNodeCount--22' : 0
, 'checkedSubNodeCount--24' : 0
, 'checkedSubNodeCount--25' : 0
, 'checkedSubNodeCount--144' : 0
, 'checkedSubNodeCount--1728': 0
};
function chkBox_click(id) // this gets called when user clicks on checkbox or text to right of checkbox.
{ // when checkbox becomes checked, then associated group also becomes shown.
var chkE = document.getElementById('chkBox--' + id); // CHecKBOX HTML element
var grpE = document.getElementById('grpBox--' + id); // GRouPbox HTML element (UL element)
var isChecked = chkE.checked;
if (isChecked)
{ // if user just checked the checkbox, and ...
if (grpE != null) // if an associated (sub)group exists for this checkbox, ...
{ grpE.style.display = ''; } // then expand/show the group element.
}
setLabelHtm(id);
var pid = getParentID(id); // Parent ID
if (id == null) { return; } // if parent id doesn't exist then we're done here.
// now 'pid' is parent ID of 'id'. for instance:
// when id == '19-a' then pid = '19'
// when id == '19-a-1-' then pid = '19-a'
var h = '';
var maxLoopCount = 12; // infinite loop protection :P
while (pid != null && --maxLoopCount >= 0)
{
chkE = document.getElementById('chkBox--' + pid); // CHecKBOX element *of parent*
var pKey = 'checkedSubNodeCount--' + pid; // Key for this Parent ID
if (isChecked) { ++dta[pKey]; } else { --dta[pKey]; }
setLabelHtm(pid);
if (h.length > 0) { h += '\n\n'; }
h += 'id = ' + id + ' isChecked = ' + isChecked
+ '\npid = ' + pid + ' chkE = ' + chkE
+ '\ndta[\'' + pKey + '\'] = ' + dta[pKey];
pid = getParentID(pid);
}
// alert(h);
} // function chkBox_click(id)
function chkBox_click8(id)
{
var chkE = document.getElementById('chkBox--' + id); // CHecKBOX element
var lblE = document.getElementById('chkLab--' + id); // CHecKbox LABel (HTML 'label' element for the checkbox)
if (chkE == null || lblE == null) { return; }
var isChecked = chkE.checked;
var g = Number(chkE.tag);
if (isChecked == false) { g = 3; chkE.tag = g; }
if (isChecked == true ) { g = 2; chkE.tag = g; }
alert(id + '\nisChecked = ' + isChecked + '\n.tag = ' + g);
} // function chkBox_click8(id)
function chkBox_clickIt(id)
{ var chkE = document.getElementById('chkBox--' + id); // CHecKBOX HTML element
if (chkE != null) { chkE.click(); }
} // function chkBox_clickIt(id)
function getParentID(id)
{
var pid = String(id); if (pid.length < 1) { return null; }
if (pid[pid.length - 1] == '-') { pid = pid.substr(0, pid.length - 1); }
var x = pid.lastIndexOf('-'); if (x < 0) { return null; }
pid = pid.substr(0, x); // now pid is id of parent
return pid;
} // function getParentID(id)
function hdrLab_click(id) // this will switch whether the associated group is hidden or shown
{// var chkE = document.getElementById('chkBox--' + id); // CHecKBOX HTML element
var grpE = document.getElementById('grpBox--' + id); // GRouPBOX HTML element (UL element)
if (grpE != null)
{ if (grpE.style.display == '')
{ grpE.style.display = 'none'; }
else
{ grpE.style.display = ''; }
}
setLabelHtm(id);
} // function hdrLab_click(id)
function setLabelHtm(id)
{ var grpE = document.getElementById('grpBox--' + id); // GRouPBOX HTML element (UL element)
var lblE = document.getElementById('hdrLab--' + id);
if (lblE == null) { return; }
var h = null; var suffix = '.';
if (grpE == null) { h = '<span style="visibility: hidden">+</span>'; }
else
{ var grpIsOpen = grpE.style.display == '';
h = '<b>' + (grpIsOpen ? '−' : '+') + '</b>';
}
var s = String(id);
if (s.length > 0 && s.substr(s.length - 1) == '-') { s = '•'; suffix = ''; }
else
{
var x = s.lastIndexOf('-') + 1;
if (x > 0) { s = s.substr(x); }
}
h += ' ' + s + suffix;
var cnt = dta['checkedSubNodeCount--' + id]; // CouNT of checked sub-nodes
if (cnt != null) // if this node is a parent node
{ var chkE = document.getElementById('chkBox--' + id); // CHecKBOX HTML element
if (chkE != null) { chkE.style.display = (cnt > 0) ? 'none' : ''; }
var hBeg = '<span class="emptyGrayBox8">';
var hEnd = '</span>';
if (cnt > 0) { h += hBeg + '<span class="checkInsideGrayBoxInsideLI"></span>' + hEnd; }
else if (chkE == null) { h += hBeg + hEnd; }
}
lblE.innerHTML = h;
} // function setLabelHtm(id)
function init()
{ //alert('yes');
hdrLab_click('1');
hdrLab_click('1-a');
hdrLab_click('19');
hdrLab_click('19-a');
hdrLab_click('19-a-1-');
hdrLab_click('19-a-2-');
hdrLab_click('19-b');
hdrLab_click('19-b-1-');
hdrLab_click('19-b-2-');
hdrLab_click('19-b-3-');
hdrLab_click('19-c');
hdrLab_click('19-c-1-');
hdrLab_click('19-c-2-');
hdrLab_click('19-c-3-');
hdrLab_click('22');
hdrLab_click('22-a');
hdrLab_click('22-b');
hdrLab_click('23');
hdrLab_click('24');
hdrLab_click('24-a');
hdrLab_click('24-b');
hdrLab_click('24-c');
hdrLab_click('25');
hdrLab_click('25-a-');
hdrLab_click('144');
hdrLab_click('144-a');
hdrLab_click('1728');
hdrLab_click('1728-a');
// alert(dta['checkedSubNodeCount--19-a']);
}
window.onload = init;
</script>
</head>
<body>
<ul style='list-style-type: none; margin-left: -1em'>
<li><label id='hdrLab--1' onclick='hdrLab_click("1")' tabindex='0' onkeypress='this.click(); return false;'></label><label id='txtLab--1' onclick='hdrLab_click("1")')> Test for short number '1':</label></li>
<ul id='grpBox--1'>
<li><label id='hdrLab--1-a' onclick='hdrLab_click("1-a")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--1-a' onclick='chkBox_click("1-a");' /><label id='txtLab--1-a' onclick='chkBox_clickIt("1-a")')>Test for short number '1' subitem:</label></li>
</ul>
<li><label id='hdrLab--19' onclick='hdrLab_click("19")' tabindex='0' onkeypress='this.click(); return false;'></label><label id='txtLab--19' onclick='hdrLab_click("19")')> Which fruit do you prefer?</label></li>
<ul id='grpBox--19'>
<li><label id='hdrLab--19-a' onclick='hdrLab_click("19-a")' tabindex='0' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--19-a' onclick='chkBox_click("19-a");' /><label id='txtLab--19-a' onclick='chkBox_clickIt("19-a")')>Apples:</label></li>
<ul id='grpBox--19-a'>
<li><label id='hdrLab--19-a-1-' onclick='hdrLab_click("19-a-1-")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--19-a-1-' onclick='chkBox_click("19-a-1-");' /><label id='txtLab--19-a-1-' onclick='chkBox_clickIt("19-a-1-")')>Red delicious</label></li>
<li><label id='hdrLab--19-a-2-' onclick='hdrLab_click("19-a-2-")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--19-a-2-' onclick='chkBox_click("19-a-2-");' /><label id='txtLab--19-a-2-' onclick='chkBox_clickIt("19-a-2-")')>Granny smith</label></li>
</ul>
<li><label id='hdrLab--19-b' onclick='hdrLab_click("19-b")' tabindex='0' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--19-b' onclick='chkBox_click("19-b");' /><label id='txtLab--19-b' onclick='chkBox_clickIt("19-b")')>Bananas:</label></li>
<ul id='grpBox--19-b'>
<li><label id='hdrLab--19-b-1-' onclick='hdrLab_click("19-b-1-")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--19-b-1-' onclick='chkBox_click("19-b-1-");' /><label id='txtLab--19-b-1-' onclick='chkBox_clickIt("19-b-1-")')>Green</label></li>
<li><label id='hdrLab--19-b-2-' onclick='hdrLab_click("19-b-2-")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--19-b-2-' onclick='chkBox_click("19-b-2-");' /><label id='txtLab--19-b-2-' onclick='chkBox_clickIt("19-b-2-")')>Yellow (ripe but not too ripe)</label></li>
<li><label id='hdrLab--19-b-3-' onclick='hdrLab_click("19-b-3-")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--19-b-3-' onclick='chkBox_click("19-b-3-");' /><label id='txtLab--19-b-3-' onclick='chkBox_clickIt("19-b-3-")')>Brown (<i>very</i> ripe)</label></li>
</ul>
<li><label id='hdrLab--19-c' onclick='hdrLab_click("19-c")' tabindex='0' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--19-c' onclick='chkBox_click("19-c");' /><label id='txtLab--19-c' onclick='chkBox_clickIt("19-c")')>Juice</label></li>
<ul id='grpBox--19-c'>
<li><label id='hdrLab--19-c-1-' onclick='hdrLab_click("19-c-1-")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--19-c-1-' onclick='chkBox_click("19-c-1-");' /><label id='txtLab--19-c-1-' onclick='chkBox_clickIt("19-c-1-")')>Orange juice</label></li>
<li><label id='hdrLab--19-c-2-' onclick='hdrLab_click("19-c-2-")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--19-c-2-' onclick='chkBox_click("19-c-2-");' /><label id='txtLab--19-c-2-' onclick='chkBox_clickIt("19-c-2-")')>Grape juice</label></li>
<li><label id='hdrLab--19-c-3-' onclick='hdrLab_click("19-c-3-")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--19-c-3-' onclick='chkBox_click("19-c-3-");' /><label id='txtLab--19-c-3-' onclick='chkBox_clickIt("19-c-3-")')>Tomato juice</label></li>
</ul>
</ul>
<li><label id='hdrLab--22' onclick='hdrLab_click("22")' tabindex='0' onkeypress='this.click(); return false;'></label><label id='txtLab--22' onclick='hdrLab_click("22")')> Which juice do you prefer?</label></li>
<ul id='grpBox--22'>
<li><label id='hdrLab--22-a' onclick='hdrLab_click("22-a")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--22-a' onclick='chkBox_click("22-a");' /><label id='txtLab--22-a' onclick='chkBox_clickIt("22-a")')>Apple juice</label></li>
<li><label id='hdrLab--22-b' onclick='hdrLab_click("22-b")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--22-b' onclick='chkBox_click("22-b");' /><label id='txtLab--22-b' onclick='chkBox_clickIt("22-b")')>Orange juice</label></li>
</ul>
<li><label id='hdrLab--23' onclick='hdrLab_click("23")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--23' onclick='chkBox_click("23");' /><label id='txtLab--23' onclick='chkBox_clickIt("23")')>Single checkmark question with no subnodes</label></li>
<li><label id='hdrLab--24' onclick='hdrLab_click("24")' tabindex='0' onkeypress='this.click(); return false;'></label><label id='txtLab--24' onclick='hdrLab_click("24")')> Best OS?</label></li>
<ul id='grpBox--24'>
<li><label id='hdrLab--24-a' onclick='hdrLab_click("24-a")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--24-a' onclick='chkBox_click("24-a");' /><label id='txtLab--24-a' onclick='chkBox_clickIt("24-a")') style='color:green'>Android!</label></li>
<li><label id='hdrLab--24-b' onclick='hdrLab_click("24-b")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--24-b' onclick='chkBox_click("24-b");' /><label id='txtLab--24-b' onclick='chkBox_clickIt("24-b")') style='color:brown'>Apple</label></li>
<li><label id='hdrLab--24-c' onclick='hdrLab_click("24-c")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--24-c' onclick='chkBox_click("24-c");' /><label id='txtLab--24-c' onclick='chkBox_clickIt("24-c")')>Linux</label></li>
</ul>
<li><label id='hdrLab--25' onclick='hdrLab_click("25")' tabindex='0' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--25' onclick='chkBox_click("25");' /><label id='txtLab--25' onclick='chkBox_clickIt("25")')>Check question with subnode check too.</label></li>
<ul id='grpBox--25'>
<li><label id='hdrLab--25-a-' onclick='hdrLab_click("25-a-")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--25-a-' onclick='chkBox_click("25-a-");' /><label id='txtLab--25-a-' onclick='chkBox_clickIt("25-a-")')>Sub-node check question</label></li>
</ul>
<li><label id='hdrLab--144' onclick='hdrLab_click("144")' tabindex='0' onkeypress='this.click(); return false;'></label><label id='txtLab--144' onclick='hdrLab_click("144")')> Test for 3-digit number:</label></li>
<ul id='grpBox--144'>
<li><label id='hdrLab--144-a' onclick='hdrLab_click("144-a")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--144-a' onclick='chkBox_click("144-a");' /><label id='txtLab--144-a' onclick='chkBox_clickIt("144-a")')>Test for 3-digit number subitem:</label></li>
</ul>
<li><label id='hdrLab--1728' onclick='hdrLab_click("1728")' tabindex='0' onkeypress='this.click(); return false;'></label><label id='txtLab--1728' onclick='hdrLab_click("1728")')> Test for 4-digit number:</label></li>
<ul id='grpBox--1728'>
<li><label id='hdrLab--1728-a' onclick='hdrLab_click("1728-a")' onkeypress='this.click(); return false;'></label><input type='checkbox' id='chkBox--1728-a' onclick='chkBox_click("1728-a");' /><label id='txtLab--1728-a' onclick='chkBox_clickIt("1728-a")')>Test for 4-digit number subitem:</label></li>
</ul>
</ul>
<div style='display: none'>
<script>
var ua = navigator.userAgent;
var ieVersion = null;
var ix = 0;
for (var v = 7; v <= 99; v++)
{
document.write('<!--[if IE ' + v + ']><hr />According to the conditional comment this is IE ' + v + '.<![endif]-->');
if ((ix = ua.indexOf('MSIE ' + v + '.')) >= 0)
{ ieVersion = '';
ix += 5;
while (ix < ua.length && '1234567890.'.indexOf(ua.charAt(ix)) >= 0)
{ ieVersion += ua.charAt(ix++);
} document.write('<hr />According to JavaScript, this is IE ' + ieVersion);
}
}
if (ieVersion == null)
{ document.write('<hr />According to JavaScript, this IE version could not be determined.');
} document.write('<hr />navigator.userAgent = ' + navigator.userAgent);
</script><hr />
<button id='webBtn1'>Fire an event</button>
<button id='btnHi' onclick='window.external.sayHelloFromJavaScript("Hello from JavaScript!", 5);'>Say Hello</button>
</div>
</body>
</html>
i also note that my project used a WebControl built for IE that needed to work as far back as WinXP. so i was limited in what i could use since it had to work for IE 7, but the nice thing is it works for way back to WinXP's latest working version of IE. i also care about using standards compliant code, so to my knowledge, my JavaScript also works for any standards-compliant browsers. i tested it in latest versions of Chrome and FF, and IE 10, IE 8 and IE 7.
there's still a good bit of code that's needed to generate the data into an HTML page, but this can solve half of your request.
in my .NET code, i had to build those JavaScript and HTML lists, which i can give in a few weeks.

You can use Dictionary objects to populate hierarchical data. This code sample might be helpful:
Dictionary<string, Dictionary<string, List<string>>> dictPage = new Dictionary<string, Dictionary<string, List<string>>>();
foreach (DataRow row in dt.Rows)
{
string sPageID = row["PageName"].ToString();
string sVersionID = row["VersionName"].ToString();
string sElementID = row["ElementName"].ToString();
if (!dictPage.ContainsKey(sPageID))
dictPage.Add(sPageID, new Dictionary<string, List<string>>());
if (!dictPage[sPageID].ContainsKey(sVersionID))
dictPage[sPageID].Add(sVersionID, new List<string>());
dictPage[sPageID][sVersionID].Add(sElementID);
}
I have used DataTable in this sample code, but you can use the same with SqlDataReader.
To create HTML you can do something like this:
StringBuilder sbHtmlUL = new StringBuilder();
sbHtmlUL.Append("<ul>");
foreach (var page in dictPage)
{
sbHtmlUL.Append("<li>");
sbHtmlUL.Append(page.Key);
sbHtmlUL.Append("<ul>");
foreach (var version in page.Value)
{
sbHtmlUL.Append("<li>");
sbHtmlUL.Append(version.Key);
sbHtmlUL.Append("<ul>");
foreach (var element in version.Value)
{
sbHtmlUL.Append("<li>");
sbHtmlUL.Append(element);
sbHtmlUL.Append("</li>");
}
sbHtmlUL.Append("</ul>");
sbHtmlUL.Append("</li>");
}
sbHtmlUL.Append("</ul>");
sbHtmlUL.Append("</li>");
}
sbHtmlUL.Append("</ul>");
In this process, you can also apply CSS classes, IDs or simple JavaScript to add a collapse/expand behavior.
Please note that I did not compare performance of this code with other approaches so I am not so sure about it, but it took 8ms in a test, on an average machine, to process 8000 records.

Related

Out of stock message passed to View If quantity <= 0

The problem is that if i have 2 items in cart that do not have the desired amount in stock, it will show only a message for one of them. Also i do not know how i can pass the information at catch{} part. Can someone please point me in the right direction, i am relatively new to asp.net mvc and programming in general.
There is a constraint in db to check quantity >= 0
Controller
public ActionResult CreateOrder()
{
List<ItemViewModel> cart = (List<ItemViewModel>)Session["cart"];
Check check = new Check();
decimal s = 0;
foreach (var item in cart)
{
var device = db.Devices.Single(d => d.DeviceID == item.Device.DeviceID);
if (device.Quantity <= 0)
{
TempData["Message"] = string.Format("Out of stock for {0}. In stock: {1}. ", device.DeviceName, device.Quantity);
return View("Cart");
}
device.Quantity -= item.Quantity;
check.DateTime = DateTime.Now;
check.CustomerName = User.Identity.Name;
s = s + item.Device.Price.Value * item.Quantity;
check.Device += item.Device.DeviceName + " x " + item.Quantity + " - $" + (item.Device.Price *= item.Quantity) + ", " ;
}
check.Total = (int)s;
check.Tax = check.Total * 20 / 100;
try
{
db.Checks.Add(check);
db.SaveChanges();
foreach (var item in cart.ToList())
{
cart.Remove(item);
}
}
catch (DbUpdateException)
{
TempData["Message"] = TempData;
return View("Cart");
}
if (User.IsInRole(RoleName.Admin))
{
return RedirectToAction("Details", "Checks", new { id = check.CheckID });
}
return RedirectToAction("PurchaseDetails", "Checks", new { id = check.CheckID });
}
View
#{
ViewBag.Title = "Cart";
}
#using WebShop.ViewModels;
<h2>Cart</h2>
<br />
#using (#Html.BeginForm("Update", "Devices", FormMethod.Post))
{
<div class="col-lg-12 col-md-12 col-sm-12">
<table class="table table-bordered table-hover" cellpadding="2" cellspacing="2" border="1">
<thead>
<tr>
<th width="5%"></th>
<th>Device</th>
<th width="7%">Price</th>
<th width="7%">Quantity</th>
<th width="7%">Total</th>
<th width="9%"></th>
</tr>
</thead>
<tbody>
#{
decimal s = 0;
decimal total = 0;
int index = 1;
decimal one = 0;
}
#foreach (ItemViewModel item in (List<ItemViewModel>)Session["cart"])
{
s = s + item.Device.Price.Value * item.Quantity;
one = item.Device.Price.Value;
total = item.Device.Price.Value * item.Quantity;
<tr>
<td><img src="#item.Device.Image" width="50" height="50" /></td>
<td>#item.Device.DeviceName</td>
<td>$#one.ToString("n2")</td>
<td><input class="form-control" type="text" name="quantity" value="#item.Quantity" style="width: 50px"></td>
<td>
$#total.ToString("n2")
#{index++;}
</td>
<td>
<button type="button" class="btn btn-bitbucket" onclick="location.href='#Url.Action("Remove", "Devices", new { id = item.Device.DeviceID })'">
<i class="fa fa-remove"></i>
</button> |
<button type="submit" class="btn btn-bitbucket">
<i class="fa fa-refresh"></i>
</button>
</td>
</tr>
}
<tr>
<td align="right" colspan="4">Total:</td>
<td>$#s.ToString("n2")</td>
</tr>
</tbody>
</table>
</div>
}
<br />
<button class="btn btn-bitbucket" type="button" onclick="location.href='#Url.Action("Shop", "Devices")'">Continue shoping</button>
<button class="btn btn-bitbucket" type="button" onclick="location.href='#Url.Action("CreateOrder", "Devices")'">Create order</button> | #TempData["Message"]
Thanks mjwills for the problem location :)
Do not know if this is the best solution but it's working so i am happy with it.
if (device.Quantity <= 0)
{
foreach (var outOfStockItem in cart)
{
string messages = string.Format("Out of stock for {0}. In stock: {1}. | ", outOfStockItem.Device.DeviceName, outOfStockItem.Device.Quantity);
TempData["Messages"] += messages;
}
return View("Cart");
}
Cart Image

asp.net paramter always null

I have a problem with my asp.net app. This is my index.html
#using BricksBreaking;
#model FieldModel
#{
ViewData["Title"] = "Game";
}
<h2>Index</h2>
<table class="field">
#for (int row = 0; row < Model.Field.RowCount; row++)
{
<tr>
#for (int column = 0; column < Model.Field.ColumnCount; column++)
{
var tile = Model.Field.Tiles[row, column];
if (tile == null)
{
<td />
}
else
{
if (Model.Field.Tiles[row, column].Color == TileColor.Red) {
<td>
<a href='/BricksBreaking/Click?r=#row?c=#column'>
<img src='/images/cervena.png' />
</a>
</td>
}if(Model.Field.Tiles[row, column].Color == TileColor.Yellow)
{
<td>
<a href='/BricksBreaking/Click?r=#row?c=#column'>
<img src='/images/zlta.png' />
</a>
</td>
}if(Model.Field.Tiles[row, column].Color == TileColor.Blue)
{
<td>
<a href='/BricksBreaking/Click?r=#row?c=#column'>
<img src='/images/modra.png' />
</a>
</td>
}
}
}
</tr>
}
</table>
And this is my controller
public class BricksBreakingController : Controller
{
ScoreServiceDatabase scoreService = new ScoreServiceDatabase();
public IActionResult Index()
{
var field = new Field(9, 9, 5);
HttpContext.Session.SetObject("field", field);
var model = new FieldModel
{ Field = field, Scores = scoreService.GetTopScores() };
return View(model);
}
public IActionResult Click(int r, int c)
{
var field = HttpContext.Session.GetObject("field") as Field;
field.ClickTile(r,c);
HttpContext.Session.SetObject("field", field);
var model = new FieldModel
{ Field = field, Scores = scoreService.GetTopScores() };
return View("Index", model);
}
}
}
Problem is. that always here at this line
<a href='/BricksBreaking/Click?r=#row?c=#column'>
Arguments passed to Function Click in controller are always 0. No matter if i write something like this
<a href='/BricksBreaking/Click?r=2?c=2'>
There will be always 0.
Can somebody help me with this? I am new to .NET.
You only need to write a ? before the first parameter. Every parameter after the first needs a &
<a href='/BricksBreaking/Click?r=2&c=2'>

How to pass Data from Controller to View with IEnumerable Model in MVC?

I have a view with 1700 records. I want to paginate them using ajax to make page load lighter. I am able to do paging and bring set of new records everytime based on the page selected.
The Problem
I am showing only 10 indexes in page-bottom, the page selected as well as 4 to the left and 5 to the right. Now I need CurrentPage value which I send everytime from jQuery/ajax to controller which I get as a ajax data parameter. The problem is in getting back Current page value persistent to view when the next page index I select. I always get the old value and not the last selected page value. I have even used ViewBag instead of tempData but no success.
View Code:
#model IEnumerable<UrCompedDAL.DBModels.SlotMachineModel>
<div class="my-properties">
<table id="tbl_slots" class="table no-margin" data-search="true" data-pagination="false">
<tbody class="orgTbody">
#foreach (var item in Model)
{
<tr>
//Code for Slot list
</tr>
}
</tbody>
</table>
<ul class="paging">
#{
int i = 1;
int pg = Convert.ToInt32(TempData["Current"]);
if (i > 0 || i == ViewBag.PageSize)
{
<li>
<<
</li>
}
if (pg < 6)
{
for (i = 1; i < 11; i++)
{
<li>
#i
</li>
}
}
else
{
for (i = pg - 4; i < pg; i++)
{
<li>
#i
</li>
}
for (i = pg; i < pg + 6; i++)
{
<li>
#i
</li>
}
}
if (i > 1 || i < ViewBag.PageSize)
{
<li>
>>
</li>
}
}
</ul>
</div>
<script>
$(document).ready(function () {
$('.lipaging').click(function () {
$("#loadingDiv").show();
$(this).addClass('active');
var pageThis = $(this).text();
var current = #TempData["Current"];
if (pageThis == '>>') {
pageThis = current +1;
}
if (pageThis == '<<') {
pageThis = current -1;
}
$.ajax({
type: 'get',
url: '#Url.Action("Index", "Game_SlotMachine")',
data: {
CurrentPage: pageThis
}
}).done(function (data) {
var startIndex = data.indexOf("<tbody");
var endIndex = data.indexOf("</tbody>");
var html = data.substring(startIndex, endIndex + 8);
$('#tbl_slots').html('');
$('#tbl_slots').html(html);
setTimeout(function () {
filter();
}, 300);
$("#loadingDiv").hide();
});
});
Controller Code:
public ActionResult Index(int id = 0, int CurrentPage = 1)
{
List<SlotMachineModel> slotmodel = new List<SlotMachineModel>();
slotmodel = UrCompedDAL.DataAccessor.Instance.GameAccessor.GetAllSlotMachines().ToList();
ViewBag.PageSize = slotmodel.Count / 10;
TempData["Current"] = CurrentPage;
slotmodel = slotmodel.Skip((CurrentPage - 1) * 10).Take(10).ToList();
return View(slotmodel);
}
Please help.
Pack your model IEnumerable<UrCompedDAL.DBModels.SlotMachineModel> into other model and set your model as a property of new model. Pass this new model as a model for your view. You will be able to pass as many data from controller as you like.
The issue is that you're re-creating the whole view, but only updating the table from the result
var html = data.substring(startIndex, endIndex + 8);
$('#tbl_slots').html('');
$('#tbl_slots').html(html);
(you should also reconsider how you extract the table from the view and use a partial instead).
None of the ajax/2nd+ rendering of the paging ul is used and is "thrown away" each time.
You can either overwrite your ul in the same way as the table or update the paging element via javascript (probably the former).
Reusing the whole view (rather than a partialview), you'd get something like:
}).done(function (data) {
var html = $("<div/>").html(data);
$('#tbl_slots').html(html.find("#tbl_slots").html());
$('ul.paging').html(html.find("ul.paging").html());

Allowing screen reader to read Kendo UI Chart data

The website I'm developing needs to comply with the WCAG 2.0 guidelines, meaning a person should be able to access all information on the site using a screen reader. Since it's a BI dashboard making heavy use of Kendo Charts it failed the test.
I need a way for screen readers to be able to read the Kendo Charts on my website, while reusing the chart's datasource.
I solved this by automatically generating a table for each chart on the page.
Create partial view which generates HTML table
#{
var divId = Guid.NewGuid().ToString();
var tableId = Guid.NewGuid().ToString();
var templateId = Guid.NewGuid().ToString();
}
/* Chart ID */
#model string
<div id="#divId" class="hiddenTable"></div>
<script>
(function () {
var template = kendo.template($("##templateId").html());
var chartData = $("##Model").data("kendoChart").dataSource;
$("##divId").prepend(template(chartData.data()));
})();
</script>
<script id="#templateId" type="text/x-kendo-tmpl">
# var columnNames = Chart.getColumnNamesFromData(data) #
<table id="#tableId">
<thead>
<tr>
# for(var columnIndex = 0; columnIndex < columnNames.length; columnIndex++) { #
<th scope="col">#= S(columnNames[columnIndex]).humanize().s #</th>
# } #
</tr>
</thead>
<tbody>
# for(var i = 0, len = data.length; i < len; i++) { #
# if (data[i][columnNames[0]] != undefined) { #
<tr>
# for(var columnIndex = 0; columnIndex < columnNames.length; columnIndex++) { #
# if(columnNames[columnIndex] == 'Date') { #
<th scope="row">#= kendo.toString(data[i][columnNames[columnIndex]], "MMMM yyyy") #</th>
#} else { #
<td>#= kendo.toString(data[i][columnNames[columnIndex]] != undefined ? data[i][columnNames[columnIndex]] : 0, "n1") #</td>
# } #
# } #
</tr>
# } #
# } #
</tbody>
</table>
</script>
Add CSS to hide table from view
.hiddenTable {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
Add img role to chart
#(Html.Kendo().Chart<MyModel>()
.Name(Guid.NewGuid().ToString())
.HtmlAttributes(new { role = "img" })
.DataSource(ds => ds
.Read("GetData", "Home")
)
)
Result

changing font size automatically

I have 3 paragraphs of text on a page...I want to change the font size of the paragraphs after every 3 seconds....is this possible?
What i want is when the page loads para 1 is 10px and para 2 is 8px and then after 3 seconds para 2 is 10px and para 1 is 8px.
I mean like using an update panel or something? js ...any way?
You can use the setInterval method to run a function at an interval:
CSS:
#para1 { font-szie: 10px; }
#para2 { font-szie: 8px; }
#para3 { font-szie: 8px; }
HTML:
<p id="para1">asdf</p>
<p id="para2">asdf</p>
<p id="para3">asdf</p>
Javascript:
window.onload = function(){
var current = 0;
var ids = ['para1', 'para2', 'para3'];
window.setInterval(function(){
current = (current + 1) % 3;
for (var i = 0; i < ids.length; i++) {
document.getElementById(ids[i]).style.fontSize = (i == current ? '10px' : '8px');
}
}, 3000);
};
Try this:
<div>
<p id="p1">Para1 </p>
<p id="p2">Para2 </p>
</div>
$(function() {
var pa1 = 20, pa2 = 8, pa3;
$('#p1').css('fontSize', pa1);
$('#p2').css('fontSize', pa2);
function fstyle() {
pa3 = pa1;
pa1 = pa2;
pa2 = pa3;
$('#p1').css('fontSize', pa1);
$('#p2').css('fontSize', pa2);
}
setInterval(fstyle, 3000);
});

Categories

Resources