MVC3: set default DisplayFor template - asp.net-mvc

The default DisplayFor helper just throws some escaped text on the page. Is there a way to wrap the default in a <span> or <div> without writing custom DisplayFor templates for each property you want to display? Instead of it spewing out
Foo
I want it to spit out
<span>Foo</span>
I've seen a lot of articles for making the custom stuff; I use those quite often. But most of my display stuff I just want to handle with simple CSS where the content is wrapped in a tag, and I can't find a reference on how to do this, or even if it's possible.

Sure use the 'object' template and override as follows from ViewData.ModelMetadata.Properties
Object template - Html.Display using ViewBag
By having your display template named object.cshtml you will apply to all types with numerable properties
There's a link to brad wilsons entry that contains the primary details
http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html

You could create your own HtmlHelper extension
public static class HtmlHelperExtensions
{
public static MvcHtmlString EnhancedDisplayFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
var stringBuilder = new StringBuilder("<span>");
stringBuilder.Append(html.DisplayFor(expression));
stringBuilder.Append("</span>");
return new MvcHtmlString(stringBuilder.ToString());
}
}
and then use it like this
#Html.EnhancedDisplayFor(model => model.MyProperty);

Related

HTML Helper how to use IEnumerable

I want to create a custom HTML Helper where I can pass a LINQ expression as a parameter, like this:
#Html.GetBackgroundColor(model => model.RiskAssessment)
I want to use it to display some custom css in an MVC view, depending on what the RiskAssessment property is.
So I created a helper method like this:
public static string GetBackgroundColor<T, TResult>(this HtmlHelper<T> htmlHelper, Expression<Func<T, TResult>> expression)
{
...
}
However, that won't compile, the error is IEnumerable does not contain a definition for 'RiskAssessment'
So I changed the method to
public static string GetBackgroundColor<T, TResult>(this HtmlHelper<IEnumerable<T>> htmlHelper, Expression<Func<T, TResult>> expression)
{
...
}
which compiles, so now I presumably have all the objects in the collection but I have no idea how to get the object I want as I can't use use the expression on the IEnumerable, there is no Where() method available. I would have thought I could do something like this:
IEnumerable<T> collection = htmlHelper.ViewData.Model;
T obj = collection.Where(expression)
but I just don't know what I am doing wrong here.
Figured it out, simple mistake. The table header row is set up with #Html.DisplayNameFor(model => modelType), and I was trying to call my custom HTML helper with these parameters. I should have been calling the method on each table row, using #Html.GetBackgroundColor(modelItem => item.RiskAssessment), and this works because I can use htmlHelper.ValueFor(expression) within the method to get the property value.
That said, I have no idea how the header row is generated as Html.DisplayNameFor uses the same method signature as my custom method but Intellisense reports that one of the Expression types is unknown. But that is not an issue for me.
Thanks.

pass values from other properties on my model to custom htmlhelper

I am trying to create a custom html helper that will actually have several html elements in it including an input type of file and input type of button.
I have that working fine, but I'd also like to include a few hidden inputs and populate the values of those with values from a few of the properties of my model. Is it possible to fetch the values of a few properties from my model in a custom #Html.MyCustomHelperFor(m => m.somefield)
my method signature looks like this:
public static MvcHtmlString MyCustomHelperFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
also, a bit off topic, would I be better suited just writing this up in a partial view?
please advise.
You can access the full model from ViewData
MyCustomHelperFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
MyModelClass model = htmlHelper.ViewData as MyModelClass;
string otherProperty = model.OtherProperty;
However this is not very flexible since it will only work for one model type (unless you do conditional checks (if (htmlHelper.ViewData is MyModelClass1) {..} else if (htmlHelper.ViewData is MyModelClass2) {..} etc.
I suggest you would be better of creating a partial view or custom display and editor templates.

How can I create a custom HTMLHelper extension that handles an item with an index

In my MVC4 website, I have a page where I'm looping through a list of items that are part of my model and putting them in a table.
My model is named JobModel and it has a list of TaskModel objects accessible in a property named Tasks.
I'm using syntax like this for each item in the list...
#Html.DisplayFor(m => m.Tasks[i].TaskName)
#Html.DisplayFor(m => m.Tasks[i].TaskName)
This works fine.
However, I have a need to create a Custom DisplayFor extension, that I'll name DisplayFor2 for this discussion.
My code looks like this...
public static IHtmlString DisplayFor2<TProperty>(this HtmlHelper<TaskModel> html, Expression<Func<TaskModel, TProperty>> ex) {
//Build my custom html here...
}
When I attempt this code,
#Html.DisplayFor2(m => m.Tasks[i].TaskName)
I get the compiler complaining that:
The type arguments for method 'IHtmlString MySite.HtmlHelpers.HelperExtensions.DisplayFor2<TProperty>(this HtmlHelper<TaskModel>, Expression<Func<TaskModel,TProperty>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
What do I need to do?
*UPDATE*
I changed my method to this, and now it works.
public static IHtmlString TableCellFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> ex)
But when I do this, I don't know the index of the child item, so it's proven useless.

Creating an MVC helper method to add "title" to the control for a tooltip

I'm creating my first MVC helper method, but can't quite get it. I want to emit the same code as the standard "#Html.TextBoxFor" but with the attribute "title" and its value taken from the model property. This is what I have so far. You can see I'm trying to just use the standard "TextBoxFor" at the end and add my own attribute to it, but that doesn't seem to be the way to do it.
public static MvcHtmlString TextBoxForWithTitle<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression)
{
var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
return htmlHelper.TextBoxFor(expression, new { #title = metaData.DisplayName });
}
Specifically, I get a compile time error:
'System.Web.Mvc.HtmlHelper<TModel>' does not contain a definition for 'TextBoxFor' and no extension method 'TextBoxFor' accepting a first argument of type 'System.Web.Mvc.HtmlHelper<TModel>' could be found (are you missing a using directive or an assembly reference?) D:\DevData\JWilliams\Code\Sandbox\URIntakeMVC2\URIntake\HtmlHelpers.cs 16 31 URIntake
The TextBoxFor is an extension method for the HtmlHelper<TModel> class which lives in the System.Web.Mvc.Html namespace.
And if you want to use an extension method you need to explicitly import its namespace with the using directive. So you are missing the using:
using System.Web.Mvc.Html;
And don't forget that you are also creating an extension method here (TextBoxForWithTitle), so when you want to use it in your view you also need to using your own TextBoxForWithTitle methods namespace:
#using URIntakeMVC2.URIntake

Extending MVC3 HTML Helpers to include custom HTML5 Attribute

I know I can add custom attributes to any given helper using an anonymous type with the attribute and value specified for it to be rendered as a HTML5 attribute however im looking to achieve the same across all HTML Helpers in a given view triggered by an externally specified helper. Similar to the same functionality you receive from the un-obtrusive JavaScript helper where it renders validation rules in the context of a form field's attributes.
Does anyone know if there is a "simple" way to inject these customisations into the helpers, or will I need to extend each of the helpers independently?
Cheers
You can't extend all methods from one centralized point (write code that will extend all your html helper methods by adding overload with additional 'htmlAttributes' parameter - may be it is possible by using IL methods generation, but it is hard way).
Each extension should be overload of your html helper method, and you can implement like in example:
public static class HtmlExtensions
{
public static string MyPager(this HtmlHelper html, string parameter1, int parameter2)
{
var builder = new TagBuilder("div");
GenerateMyPagerBody(builder , parameter1, parameter2); // insert body into tag
return builder.ToString(TagRenderMode.SelfClosing);
}
public static string MyPager(this HtmlHelper html, string parameter1, int parameter2, object htmlAttributes)
{
var builder = new TagBuilder("div");
GenerateMyPagerBody(builder , parameter1, parameter2);
builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
return builder.ToString(TagRenderMode.SelfClosing);
}
}

Resources