#Html.DisplayFor(modelItem => item.Quantity)*(modelItem => item.PartsPrice)
I can display 1 or both item but unable to multiply any easy solution for above situation?
Create Price property in your modal as shown below than after use of Price property to display multiplication in your view page.
Price property declaration in modal.
public decimal Price
{
get
{
return Quantity * PartsPrice;
}
}
Display in razor view page as follow.
#Html.DisplayFor(modelItem => item.Price)
Hope it will be helpful.
You can not calculate like that. You can calculate in model, otherwise if you want to calculate the values in view, you can try the following
#{
var result = Model.Quantity * Model.PartsPrice; // Calculate the price
<span>#result</span>
}
#result will display the calculated value
if suppose the model is collection then, use foreach loop
#{
foreach (var item in Model)
{
var result = item.Quantity * item.PartsPrice; // Calculate the price
<span>#result</span>
}
}
Related
(NUBE) I am trying to loop thru a view model and show rows when a field has a particular value. (IE In a Master/Detail model I have pulled all my orders in one list and all the detail in another. When the user picks the particular order from the first list I just want to iterate thru the detail list and show those line items for edit/delete purposes.
This code works from testing if I hardcode the value (2953) but I wish to pass a value and am not sure if Viewbag or razor is the way to go. I would like to maintain a consistent framework throughout.
#foreach (var row in Model.SplitTankAssignmentItems.Where(x => x.MeterValueID == 2953) ) // row.splitTicketID) )
{
<tr id="#row.SplitTankID>
:
:
:
</tr>
}
The ViewBag is exactly for this purpose.
On your control-action method you can set up the ViewBag and in your view you can read it.
Controller
public IActionResult Index()
{
:
ViewBag.ValueToUse = 2953
Return View(model);
}
View
#foreach (var row in Model.SplitTankAssignmentItems.Where(x => x.MeterValueID == (int)ViewBag.ValueToUse) ) // row.splitTicketID) )
{
<tr id="#row.SplitTankID>
:
:
:
</tr>
}
Notes: Remeber to cast your ViewBag property to the type you need, and keep in mind that ViewBag is only for one call, usually to take information from controller to view. It won't stay from view to controller neither from an action method to action method (RedirectTo)
I am using nuget Package named ExcelDataReader in MVC application to read Excel sheet and convert it to HTML.All sounds goof but i am not able to read special character from excel sheet.For example is cell value is "59%" but its reading 0.59.So how can i get exact same string value from excel.I am using following code in Controller to read and display excel to html.
public ActionResult ViewExcelFileData(long? id, int sheetindex)
{
var excelfile = db.ExcelUpload.FirstOrDefault(x => x.FileID == id);
string filePath= string.Format(Server.MapPath("~/App_Data/ExcelUploads/Labor_Excel/") + excelfile.FileName);
System.IO.File.GetAccessControl(filePath);
FileStream stream = System.IO.File.Open(filePath, FileMode.Open, FileAccess.Read);
IExcelDataReader reader = null;
if (excelfile.FileName.EndsWith(".xls"))
{
reader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else if (excelfile.FileName.EndsWith(".xlsx"))
{
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}
reader.IsFirstRowAsColumnNames = true;
DataSet result = reader.AsDataSet();
reader.Close();
return View(result.Tables[sheetindex]);
}
By returning datatable in View side I am using Following Code in Cshtml.
<table class="gridtable" id="table-1">
<thead class="fixed_headers">
<tr>
#foreach (DataColumn col in Model.Columns)
{
<th>#col.ColumnName</th>
}
</tr>
</thead>
<tbody>
#foreach (DataRow row in Model.Rows)
{
<tr>
#foreach (DataColumn col in Model.Columns)
{
<td>#row[col.ColumnName]</td>
}
</tr>
}
</tbody>
</table>
So is it possible in controller side or View side I can get 59% instead of 0.59?
Here is Two images in which one is belongs to excel and second is HTML.
IMAGE :1
IMAGE 2 :
ExcelDataReader currently does not expose any formatting information, it provides you with the raw values except for dates that are converted to DateTime.
There's an open issue about extending it to provide formatting information, https://github.com/ExcelDataReader/ExcelDataReader/issues/215.
Instead of using the AsDataSet() method, you could read the row one by one and read the value as string. Drawback for this is you need to specify the columns one by one which is a maintainability issue.
while (reader.Read())
{
var value = reader.GetString(0); //Get value of first column
}
I suspect that the AsDataSet() converts the data to its respective data type that's why you are seeing the converted decimal value instead of the actual value in the excel.
A common way to fill a table is:
#For Each item In Model
Dim currentItem = item
#<tr>
<td>currentitem.Data1</td>
<td>currentitem.Data2</td>
<td>currentitem.Data3</td>
</tr>
Next
But for some reasons (to control the order of columns), I would like to refer to the fields by their string names, something like this:
#For Each item In Model
Dim currentItem = item
#<tr>
<td>currentitem("Data1").Value</td>
<td>currentitem("Data2").Value</td>
<td>currentitem("Data3").Value</td>
</tr>
Next
Is it somehow possible?
Ok - now that we have established that you need to change the order of your view model, let's do a little bit of work to your view model to make it easier to change the order. Given that we have to change the order of how we display things, we have to have a way to track what order to display them in. To change on the fly in the view without having different views with different orders (could get messy fast) - so let's just update our model a little bit.
Let assume this is your view model
public class OriginalViewModel{
public string Data1 {get;set;}
public string Data2 {get;set;}
public string Data3 {get;set;|
}
Let's create a new class called DataProperty. This will hold the data objects as well as allow us to set a display order that we can sort on later.
public class DataProperty{
public int DisplayOrder {get;set;}
public string Data {get;set;}
}
Now, let's update your view model to be a set of these DataProperties. We are using something we can enumerate and order by the display order.
public class UpdatedViewModel{
public IEnumerable<DataProperty> DataSet {get;set;}
}
Now, you can set the display order on each one of your property elements.
var listOfItems = new List<DataProperty>();
listOfItems.Add(new DataProperty{Data = "data1", DisplayOrder = 2});
listOfItems.Add(new DataProperty{Data = "data2", DisplayOrder = 3});
listOfItems.Add(new DataProperty{Data = "data3", DisplayOrder = 1});
var model = new UpdatedViewModel();
model.Data = listOfItems;
In your view, order by the display order property. Note we can now use Linq to order our data appropriately based on the requirements for this view.
#{foreach(var item in Model.OrderBy(x=>x.Data.DisplayOrder){
<tr>
<td>#item.Data</td>
<td>#item.Data</td>
<td>#item.Data</td>
</tr>
}}
which should render in HTML
<tr>
<td>data3</td>
<td>data1</td>
<td>data2</td>
</tr>
Thank you Tommy,
I tried to solve it in simple way and did this:
For example, I have a Viewdata that contains the order of the columns:
ViewData("columnsorder")="|3|1|2|"
and then, I just loop through ViewData and set the columns.
#For Each item In Model
Dim currentItem = item
#<tr>
#For i As Integer = 1 To ViewData("columnsorder").ToString.Split("|").Count - 2
Dim ind As Integer = ViewData("columnsorder").ToString.Split("|")(i)
Select Case ind
Case 1#<td>#currentItem.Data1</td>
Case 2#<td>#currentItem.Data2</td>
Case 3#<td>#currentItem.Data3</td>
End Select
Next
</tr>
Next
I've got what appears to be a fairly basic loop:
<% foreach (var item in Model.Items.OrderByDescending(b => b.ItemDateTime)) {%>
Instead of looping through all the items I just want to output the first item, how can I do this?
You can use FirstODefault() method of your collection. Try something like this:
// check if the model contains any item
if (Model.Items.Count() > 0)
{
//show the item...
var firstItem = Model.Items.OrderByDescending(b => b.ItemDateTime).FirstOrDefault();
}
To expand on Felipe's comment, it's better design usually to put things like this in your view models or controllers, not the views.
You could put this on your viewmodel
public Item EarliestItem
{
get { return Items.OrderByDescending(b => b.ItemDateTime).FirstOrDefault(); }
}
Then use this in your view
Or whatever it is you want to do with the earliest item.
All,
I've read through a lot of posts about Checkboxes and ASP.MVC but I'm not that much wiser.
My scenario:
I have a strongly typed View where I pass a collection of summary objects to the view for rendering in a for-each. This summary object contains label data based on a unique id. I also add a checkbox to the row so do so via:
<td>
<%= Html.CheckBox("markedItem", Model.MarkedItem, new { TrackedItemId = Model.Id })%>
</td>
When I perform a POST to get the submitted results my action method takes the strongly typed ViewModel back but the original summary object that I used to create the list is not populated.
Ok, this is annoying, but I can understand why so I'll live with it.
What I then do is to add a new property to my ViewModel called "MarkedItem" which is a string collection.
On postback this marked item is filled with the before and after states if the checkbox has changed but nothing to tell me which key they were for. Just to clarify, if I send this
TrackedItemId = A, Value = false
TrackedItemId = B, Value = true
TrackedItemId = C, Value = false
and set the page to this:
TrackedItemId = A, Value = true
TrackedItemId = B, Value = true
TrackedItemId = C, Value = false
I will get back this:
MarkedItem[0] = true
MarkedItem[1] = false
MarkedItem[2] = true
MarkedItem[3] = false
in other words [0] is the new value and [1] is the old value, [2] and [3] represent values that haven't changed.
My questions are:
Is this right - that I get before and after in this way? Is there any way to only send the latest values?
How can I get hold of the custom attribute (TrackedItemId) that I've added so that I can add meaning to the string array that is returned?
So far I like MVC but it not handling simple stuff like this is really confusing. I'm also a javascript noob so I really hope that isn't the answer as I'd like to return the data in my custom viewmodel.
Please make any explanations/advice simple :)
<p>
<label>
Select project members:</label>
<ul>
<% foreach (var user in this.Model.Users)
{ %>
<li>
<%= this.Html.CheckBox("Member" + user.UserId, this.Model.Project.IsUserInMembers(user.UserId)) %><label
for="Member<%= user.UserId %>" class="inline"><%= user.Name%></label></li>
<% } %></ul>
and in the controller:
// update project members
foreach (var key in collection.Keys)
{
if (key.ToString().StartsWith("Member"))
{
int userId = int.Parse(key.ToString().Replace("Member", ""));
if (collection[key.ToString()].Contains("true"))
this.ProjectRepository.AddMemberToProject(id, userId);
else
this.ProjectRepository.DeleteMemberFromProject(id, userId);
}
}
With thanks to Pino :)
ok, one hack I've come up with - I really hate that I have to do this but I don't see another way round it and I'm sure it will break at some point.
I've already implemented by own ModelBinder to get round some other issues (classes as properties for example) so have extended it to incorporate this code. We use Guid's for all our keys.
If there are any alternatives to the below then please let me know.
Html
<%= Html.CheckBox("markedItem" + Model.Id, false)%>
C#
(GuidLength is a const int = 36, Left and Right are our own string extensions)
//Correct checkbox values - pull all the values back from the context that might be from a checkbox. If we can parse a Guid then we assume
//its a checkbox value and attempt to match up the model. This assumes the model will be expecting a dictionary to receive the key and
//boolean value and deals with several sets of checkboxes in the same page
//TODO: Model Validation - I don't think validation will be fired by this. Need to reapply model validation after properties have been set?
Dictionary<string, Dictionary<Guid, bool>> checkBoxItems = new Dictionary<string, Dictionary<Guid, bool>>();
foreach (var item in bindingContext.ValueProvider.Where(k => k.Key.Length > GuidLength))
{
Regex guidRegEx = new Regex(#"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$");
if (guidRegEx.IsMatch(item.Key.Right(GuidLength)))
{
Guid entityKey = new Guid(item.Key.Right(GuidLength));
string modelKey = item.Key.Left(item.Key.Length - GuidLength);
Dictionary<Guid, bool> checkedValues = null;
if (!checkBoxItems.TryGetValue(modelKey, out checkedValues))
{
checkedValues = new Dictionary<Guid, bool>();
checkBoxItems.Add(modelKey, checkedValues);
}
//The assumption is that we will always get 1 or 2 values. 1 means the contents have not changed, 2 means the contents have changed
//and, so far, the first position has always contained the latest value
checkedValues.Add(entityKey, Convert.ToBoolean(((string[])item.Value.RawValue).First()));
}
}
foreach (var item in checkBoxItems)
{
PropertyInfo info = model.GetType().GetProperty(item.Key,
BindingFlags.IgnoreCase |
BindingFlags.Public |
BindingFlags.Instance);
info.SetValue(model, item.Value, null);
}