Using EditorFor template for DisplayFor in MVC4? - asp.net-mvc

I'm using an Editor Template to make an Html.EditorFor(property) in my viewModel's view. There's a different .cshtml file containing "#Html.EditorFor(property)".
Now, depending on the value of a property of my viewModel, I need to display a DisplayFor instead.
I tried doing this by adding some conditional logic in my EditorTemplate but can't seem to access the properties of my viewModel from there (since the editor template is using #model.someOtherModel and not #viewModel). So if I can say something like
// Razor
if(true)
{ EditorFor(property) }
else {DisplayFor(property)}
in my viewModel's view, that would work. I just don't know how to define a "Display Template" for my object, in the same way I defined an Editor Template.
Another solution might be accessing the viewModel data from the Editor template... is this possible?

In Razor, you should be using something like the following syntax:
#if (condition) {
#Html.EditorFor(modelItem => model.property)
} else {
#Html.DisplayFor(modelItem => model.property)
}
Are you getting a specific error you can share?

Related

What is the Exact use of DisplayFor in mvc razor view?

What is the Exact use of DisplayFor in mvc razor view? Because it will show only string that matches the model property we pass. But in Razor view, we can directly show the property value using model.propertyvalue
What is the difference between below codes,
<span> #Html.DisplayFor(m => m.propertyValue)</span>
VS
<span> #Model.propertyValue</span>
When using #Html.DisplayFor(m => m.Property) allows you to take advantage of DataAttributes in your model class. An example would be using [DisplayFormat(NullDisplayText = "whatever you want to display when null")]. I typically have my values display an em-dash when null. Accessing the property directly with #Model.Property will bypass those attributes.

How #Html.EditorFor resolve or point to right template

just read the article for how to work with template for re-usability from this url http://www.iminfo.in/post/mvc-multiple-checkboxes-select-in-html-table-bootstrap
this article show just we need to create a template file in editor template folder with viewmodel name.
i just like to know how MVC #Html.EditorFor can point or pickup to right template file. need some guide line like how MVC resolve right template to pick up. thanks
By default templates are resolved by data type so if you use
#Html.EditorFor(model => model.ProductViewModel)it will use EditorTemplates/ProductViewModel.cshtml template.
However if you need to use a different template you can use an override of #Html.EditorFor(model => model.ProductViewModel, "yourTemplateName") that accepts template name.
Additional option is to set a template by using UIHint attribute on the property for example:
public class ComplexModel
{
//will search for EditorTemplates/SomeProductModelTemplate.cshtml
[UIHint("SomeProductModelTemplate")]
public ProductViewModel ProductModel {get;set;}
}
The template is resolved by data type. In your example you have editor templates folder with a ProductViewModel template. If you then create a view under the home directory using the EditorFor method with a ProductViewModel type then MVC will resolve the custom editor template. Similarly, if you created a DateTime.cshtml file under editor templates then that would be used for EditorFor method calls with a DateTime parameter.
#Html.EditorFor(model => model.ProductViewModelItem) //will use the custom template
#Html.EditorFor(model => model.StringItem) //will not use the custom template
You can also do the same with DisplayTemplates for DisplayFor or any of the other Html "for" helpers.

Is there any way to create a custom MVC Razor element like "text"?

I want to create a custom razor tag like <text></text> to decide what to do with the html code inside of it. Is there any way to create razor elements like <text></text> element and add it to the razor engine?
I don't want to create any HtmlHelpers for this.
For Examle:
<WYSYWIG>
Hello There!
</WYSYWIG>
or
<WeatherChart City="NY">
</WeatherChart>
Explanation:
Well the idea is to have server tags to be translated (Parsed) to html codes by the attributes given to them. This kind of codes helps junior developers not to be involved with the complexity of controls.
The closest thing to what you are describing is to create display or editor templates. You can then define a template for a model and use it with #Html.DisplayFor() in the view.
Here is a good blog post to get you started aspnet mvc display and editor templates and a quick overview of the structure below.
Example
Model - WeatherChartModel.cs
public class WeatherChartModel
{
}
Display template - WeatherChart.cshtml
<div class="weather-chart">
// Some other stuff here
</div>
View - Index.cshtml
#model WeatherChartModel
#Html.DisplayForModel() // This will output the template view for the model
In order to create custom element handling in razor, such as <text>, you'd need to implement a custom System.Web.Razor.dll (which is responsible for parsing the document). Specifically, the class you're looking to re-implement would be the System.Web.Razor.Parser.HtmlMarkupParser.
However, I don't believe this is necessary given how flexible the framework itself is. If you're looking to keep things modular, have a look at either using DisplayTemplates/EditorTemplates or consider writing your own extension method. For example, either of the following would be more ideal:
#* TextField is decorated with UIHint("WYSIWYG"), therefore
calling ~/Views/Shared/EditorTemplates/WYSIWYG.cshtml *#
#Html.EditorFor(x => x.TextField)
#* WeatherField is decorated with UIHint("WeatherChart"), therefore
calling ~/Views/Shared/DisplayTemplates/WeatherChart.cshtml *#
#Html.DisplayFor(x => x.WeatherField)
Alternatively:
#* Custom extension method *#
#Html.WysiwygFor(x => x.TextField)
#* Another custom extension method *#
#Html.WeatherChartFor(x => x.WeatherField)

Can one MVC Edit Template delegate to another?

I have a strongly-typed Razor 2 editor template. When the view model meets certain conditions, I want the view to delegate to an alternative template of the same type. I use the TemplateName argument to the EditorFor helper to select the alternative template:
#model MyType
#if (Model.IsSpecialCase)
{
#Html.EditorFor(m => m, "SpecialCaseTemplate")
}
else
{
#* Default markup *#
}
Problem is, Razor does not call the alternative template; it simply passes over the EditorFor method. If I change the type of the second template, it shows it correctly. I can work around this using a Partial View, but I would rather not, as I have a scheme going with Editor Templates that I want to stick to.
Anyone know how I can get this to work?
Edit
Looks like this has something to do with the behaviour described here: ASP.net MVC - Using EditorFor with the same model type twice. In short, that MVC does not support using the EditorFor method on the same object twice.
The best way to do this, is by returning a different view from your Controller:
public ActionResult someaction(){
var Model = ...;
if (Model.IsSpecialCase){
return View("SpecialCaseTemplate");
}
else{
return View();
}
}
Alternatively, you could do in the view like this:
#model MyType
#if (Model.IsSpecialCase)
{
Html.RenderPartial("SpecialCaseTemplate", model);
}
else
{
#* Default markup *#
}

Use ASP.NET MVC DisplayTemplate implicitly

I have some code like this in a cshtml view
#{ int i = 0;
foreach (var record in Model.Records)
{
<tr>
<td>#record.CreatedDate</td>
<td>#Html.DisplayFor(x => x.Records[i].CreatedDate)</td>
</tr>
i++;
}
}
and in my ~/Views/Display folder I have a file called DateTime.cshtml with this in
<p>#ViewData.Model.ToShortDateString()</p>
so my view is rendering two version of the CreatedDate, one with the full DateTime string and one with the short date string.
Can I configure my ASP.NET MVC4 project to use the display template I have created whenever it displays a DateTime, without calling DisplayFor explicitly? ie how can the line '#record.CreatedDate' use my DateTime template?
No you can't. there is no way to configure MVC to use a template with this code:
'#record.CreatedDate'
You will have to keep using DisplayFor which isn't too much to write by the way...

Resources