I'm currently using a DisplayTemplate to show a property of my Model:
#Html.DisplayFor( m => m.TheProperty, "myTemplate")
The template output the html for an image, which source depends on whether the Model (TheProperty) is null or not.
Now, I'm replacing all bindings in my View with knockout binding. So it seems I can no longer use DisplayTemplates, can I ? How would I pass the template a Model since now controls are bound to a js ViewModel ?
The equivalent in KO would be the template binding, its syntax is not as nice however, its like
<div data-bind="template: { name: 'display-for-my-property', data: myProperty }"></div>
Where display-for-my-property is the id of a script tag with the template for myProperty
As you can see this synstax is pretty messy, I have made my own library that solves this
https://github.com/AndersMalmgren/Knockout.BindingConventions
Using my lib the same scenario would look like
<div data-name="myProperty"></div>
Example
http://jsfiddle.net/xJL7u/
You could extend my lib so you can do
<div data-display="myProperty"></div>
And
<div data-editor="myProperty"></div>
Related
in MVC5 , what does #model, #html and #using mean, why and when we usually use ( # ) and which word follow it ?
For example : #model MVC_Project2.Models.stufftable is written in the first of re.cshtml page
stufftable is a table which is belong to users to create new user and the following code is written in the same page to create two textbox with two labels two labels to show the login page :
#using (Html.BeginForm())
{
<div>
#Html.LabelFor(u => u.stuffname)
#Html.TextBoxFor(u => u.stuffname)
</div>
<div>
#Html.LabelFor(u => u.stuffpass)
#Html.PasswordFor(u => u.stuffpass)
</div>
<input type="submit" />
}
in a .cshtml file, everything that goes in it is HTML. So it will get written out exactly as its written.
In other words, if you just typed
model blah
without the # then when you render the view, it will actually display the words model blah on the page.
The # sign is a directive to tell the Razor engine that what follows is code, and it should compile that rather than simply write it to the output.
so when you type
#model blah
This is compiled by razor, and tells the Razor engine that the type of the model is 'blah', so that when you use the keyword Model (note the capital M and you would have to use the # sign as well) it will refer to the model you have defined (in this case blah).
So if you write
#model blah
#Model.Foo
then, if blah.Foo contained the number 14, it would write the number 14 to the output. As you might have surmised, the # symbol has many uses, so if you say #Model.Foo you're actually doing something like Response.Write(Model.Foo).
In general, the # symbol is used to transition from HTML mode, to code mode, in the same way the old ASPX code nuggets were used <% ... %>, however razor is a little smarter and understands the context of your code so it can infer where your code ends most of the time, so there is no need to have an ending bracket like in the old days.
#using is just like in C# code, it is the using statement that disposes of disposable resources after the block has ended. Razor uses this technique in many cases to signify the end of a block of code. So, for instance saying:
#using(Html.BeginForm()) {
....
}
The Html.BeginForm helper returns an object that defines an IDisposable interface, that gets called when the using statement ends, so BeginForm() in this case outputs a <form> tag, and when the IDisposable.Dispose() method is called at the end of the using statement, it outputs </form>. It's a technique that's used to wrap other code that outputs tags so that it can properly close their html.
#Html is also just C#. However, it's calling the HtmlHelper object (Razor defines an object called Html in the "ViewPage" class that backs the view, this Html object is of type HtmlHelper) and it calls various C# extension methods which have been defined on the HtmlHelper object. If you don't know what a C# Extension Method is, it's a way to extend objects without those objects having to be rewritten, this is more advanced C#. Suffice it to say, that something like #Html.TextBox() calls a method of type HtmlHelper.TextBox(), so it's just a C# method you can call, but these methods are created specifically as helpers to help you create your HTML.
There is a lot to this really, and if you don't understand the concepts I've discussed, then you really need to learn more about C# and/or HTML, as you are likely getting in over your head.
Clean and Simple: # is Razor Syntax. It helps you to insert C# code into your views (HTML code).
For Example:
#DateTime.Now
Will show you current date and time.
The # is used for directives in Razor code. #model, for example, binds the View to the model. # is also used to execute and print out back-end C# code in HTML. When you use #Html it calls a helper class that is part of the Mvc framework which returns an MvcHtmlString.
We have an ASP.NET MVC 5.0 application that uses both Knockout and Kendo UI. For historical reasons, we'd rather stay with Knockout rather than use Kendo's MVVM features however, we've notcied that Kendo isn't completely compatible with KO. To get around this incompatibility between the two frameworks I've been investigating the Knockout-Kendo library (v0.9.0). The Knockout-Kendo library works but I've noticed that when I use Kendo's Html Helpers the .k-input class is being applied to the outermost span that encapsulates the widget; obviously, this changes the appearance of widget and, in my view, shouldn't be happening. So far, I've not been able to find a workaround that stops the .k-input class from being applied inappropriately.
Initially, I thought the .k-input class might be being applied because I was missing some subtlety in the binding syntax that the Knockout-Kendo library uses but using "standard" KO bindings take me back to square one, Kendo widgets don't respond to all bindings. To illustrate:
<div class="form-group">
<label for="Start">Start</label>
#Html.Kendo()
.DatePickerFor(m => m.Start)
.HtmlAttributes(new { data_bind = "kendoDatePicker: {enabled: enabledFlag, value: startDate}" })
</div>
declaring a widget using this binding syntax works but inappropriately applies the .k-input class.
<div class="form-group">
<label for="Start">Start</label>
#Html.Kendo()
.DatePickerFor(m => m.Start)
.HtmlAttributes(new { data_bind = "enabled: enabledFlag, value: startDate" })
</div>
and declaring a widget using this binding syntax, just doesn't work correctly.
So, my question is this: is it possible to use the Knockout-Kendo library with Kendo's Html Helpers or, is it only designed to be used with html input tags?
The HTML helpers will try to initialize the widget, as will the KO binding (when bindings are applied). So, if you are using knockout-kendo, you would want to add your binding to a normal element, so that it is initialized properly with the right handlers to do two-way binding with your view model.
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)
Is there a reason to use preferably one of these:
#Model.Property
#Html.DisplayFor(m => m.Property)
I never arrived in a crossroad where one works differently from the other.
There is any difference?
Model.Property - as you know - will just write out the value of the property in question. Html.DisplayFor(m => m.Property), on the other hand, will call a display template, which can render out other markup around the property value.
For example, you might define a display template like so:
#model String
<div class="property-wrapper">
<p>#Model.Property</p>
</div>
The surrounding divs will be rendered around the value of the property when using DisplayFor (if the display template is selected, which typically means it has a filename matching the property's type, is specified in the UIHint attribute for the property, or is explicitly specified in the call to DisplayFor.
You also have access to model metadata in your display templates, meaning you can do something like this:
<div class="property-label">
#Html.DisplayNameForModel()
</div>
<div class="property-value">
#Model.Property
</div>
Display templates give you a huge amount of flexibility and reusability. The best way to explore this is to start building custom templates and see where it takes you.
I have a lot of content-heavy views in my ASP.NET MVC 2 site. These contain several re-occurring HTML patterns. When using ASP.NET Webforms, a class derived from WebControl could encapsulate these patterns. I'd like some pointers on the correct approach for this problem with MVC.
Detailed Explanation
Patterns not unlike the following HTML markup keep occurring throughout these views. The markup renders into an isolated a box of content:
<div class="top container">
<div class="header">
<p>The title</p>
<em>(and a small note)</em>
</div>
<div class="simpleBox rounded">
<p>This is content.</p>
<p><strong>Some more content</strong></p>
</div>
</div>
This is a trivial example, but there are more complex recurring patterns. In ASP.NET Webforms I would have abstracted such code into a WebControl (let's say I'd have named it BoxControl), being included on a page like this:
<foo:BoxControl runat="server">
<Header>The title</Header>
<Note>(and a small note)</Note>
<Content>
<p>This is content.</p>
<p><strong>Some more content</strong></p>
</Content>
</foo:BoxControl>
This abstraction makes it easy to adapt the way the box is constructed throughout the site, by just altering the BoxControl source. It also keeps the static HTML content neatly together in the View Page, even when combining several BoxControls on a page. Another benefit is that the HTML used as content is recognized by the IDE, thus providing syntax highlighting/checking.
To my understanding, WebControls are discouraged in ASP.NET MVC. Instead of a WebControl, I could accomplish the abstraction with a partial view. Such a view would then be included in a View Page as follows:
<%= Html.Partial("BoxControl", new {
Header="The Title",
Note="(and a small note)",
Content="<p>This is content.</p><p><strong>Some more content</strong></p>"});
%>
This is not ideal, since the 'Content' parameter could become very long, and the IDE does not treat it as HTML when passed this way.
Considered Solutions
Strongly-Typed ViewModels can be passed to the Html.Partial call instead of the lengthy parameters shown above. But then I'd have to pull the content in from somewhere else (a CMS, or Resource file). I'd like for the content to be contained in the View Page.
I have also considered the solution proposed by Jeffrey Palermo, but that would mean lots of extra files scattered around the project. I'd like the textual content of any view to be restricted to one file only.
Should I not want to abstract the markup away? Or is there maybe an approach, suitable for MVC, that I am overlooking here? What is the drawback to 'sinning' by using a WebControl?
There is a solution to this problem, although the way to get there is a little more clutsy than other frameworks like Ruby on Rails.
I've used this method to create markup for Twitter Bootstrap's control group syntax which looks like this:
<div class="control-group">
<label class="control-label">[Label text here]</label>
<div class="controls">
[Arbitrary markup here]
</div>
</div>
Here's how:
1) Create a model for the common markup snippet. The model should write markup on construction and again on dispose:
using System;
using System.Web.Mvc;
namespace My.Name.Space
{
public class ControlGroup : IDisposable
{
private readonly ViewContext m_viewContext;
private readonly TagBuilder m_controlGroup;
private readonly TagBuilder m_controlsDiv;
public ControlGroup(ViewContext viewContext, string labelText)
{
m_viewContext = viewContext;
/*
* <div class="control-group">
* <label class="control-label">Label</label>
* <div class="controls">
* input(s)
* </div>
* </div>
*/
m_controlGroup = new TagBuilder("div");
m_controlGroup.AddCssClass("control-group");
m_viewContext.Writer.Write(m_controlGroup.ToString(TagRenderMode.StartTag));
if (labelText != null)
{
var label = new TagBuilder("label");
label.AddCssClass("control-label");
label.InnerHtml = labelText;
m_viewContext.Writer.Write(label.ToString());
}
m_controlsDiv = new TagBuilder("div");
m_controlsDiv.AddCssClass("controls");
m_viewContext.Writer.Write(m_controlsDiv.ToString(TagRenderMode.StartTag));
}
public void Dispose()
{
m_viewContext.Writer.Write(m_controlsDiv.ToString(TagRenderMode.EndTag));
m_viewContext.Writer.Write(m_controlGroup.ToString(TagRenderMode.EndTag));
}
}
}
2) Create a nifty Html helper
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using My.Name.Space
namespace Some.Name.Space
{
public static class FormsHelper
{
public static ControlGroup ControlGroup(this HtmlHelper helper, string labelText)
{
return new ControlGroup(helper.ViewContext, labelText);
}
}
}
3) Use it in the view (Razor code)
#using (Html.ControlGroup("My label"))
{
<input type="text" />
<p>Arbitrary markup</p>
<input type="text" name="moreInputFields" />
}
This is also the way MVC framework renders a form with the Html.BeginForm method
Well you wouldn't render the partial like that, pass it a strongly-typed ViewModel, like this:
<%= Html.RenderPartial("BoxControl", contentModel) %>
contentModel is the ViewModel (just a POCO-like storage mechanism for your views), which the strongly typed partial view would bind to.
So you can do this in your partial view:
<h1><%: Model.Header %></h1>
<p><%: Model.Content %></p>
etc etc
After considering the answers and running an experiment, I'm inclined to adhere to the pure MVC approach and duplicate some presentation code throughout View Pages. I'd like to elaborate on the rationale for that decision.
Partial View
When using a Partial View, The content for the box needs to be passed as a View Model, making the View Page less readable versus declaring the content HTML on the spot. Remember that the content does not come from a CMS, so that would mean filling the View Model with HTML in a controller or setting a local variable in the View Page. Both of these methods fail to take advantage of IDE features for dealing with HTML.
WebControl
On the other hand, a WebControl-derived class is discouraged and also turns out to have some practical issues. The main issue that the declarative, hierarchical style of traditional ASP.NET .aspx pages just does not fit the procedural style of MVC.NET View Pages. You have to choose for either a full blown traditional approach, or go completely MVC.
To illustrate this, the most prominent issue in my experimental implementation was one of variable scope: when iterating a list of products, the MVC-way is to use a foreach loop, but that introduces a local variable which will not be available in the scope of the WebControl. The traditional ASP.NET approach would be to use a Repeater instead of the foreach. It seems to be a slippery slope to use any traditional ASP.NET controls at all, because I suspect you'll soon find yourself needing to combine more and more of them to get the job done.
Plain HTML
Forgoing the abstraction at all, you are left with duplicate presentation code. This is against DRY, but produces very readable code.
It doesnt look like webforms has that much less html to me, it seems more like a lateral move. Using a partial in MVC can make it cleaner but the html markup you needed will still be there, in one place or another. If its mostly the extra html that bothers you, you might take a look at the NHaml view engine or check out haml
the haml website.
I'm by no means a Haml expert but the html does look a lot cleaner...
.top container
.header
%p
The title
%em
(and a small note)
.simpleBox rounded
%p
This is content.
%p
Some more content