I have a IList
as a property named Tags
in my model. How do I name the files for display and editor templates to respect it when I call
EditorFor or DisplayFor is access ViewData.Model property.
Sample solution
<% foreach(var tag in Model.Tags) { %>
<%= Html.EditorFor(m => tag) %>
<% } %>
Other solution
<% for (var i=0;i<Model.Tags.Count();i++) { %>
<%= Html.EditorFor(m => m.Tags[i]) %>
<% } %>
Hope this code!
I had the same problem today. Hope this helps:
forach(var tag in Tags) {
<%= Html.EditorFor( _ -> tag) %>
}
If you absolutely want to do sth. like
Html.EditorFor(mymodel=>mymodel.Tags)
Then you will have to:
Create a UserControl (TagList.ascx) and add an UIHint attribute to MyModel
class MyModel {
[UIHint("Taglist")]
IList<Tag> Tags {get; protected set;}
}
You could create a custom collection type and name the editor to match that.
Assuming you created custom collection called Tags
you could change your model to:
class MyModel
{
Tags Tags { get; protected set;}
}
Then you would name your editor and display templates Tags.ascx
.
Which would make your view code work like you wanted:
<%= Html.EditorFor(t => t.Tags) %>
For the custom collection you basically just create a wrapper around an implementation of a generic collection and expose it's methods and properties:
public class Tags : IList<Tag>
{
//Use a private List<Tag> to do all the
//heavy lifting.
private List<Tag> _tags;
public Tags()
{
_tags = new List<Tag>();
}
public Tags(IEnumerable<Tag> tags)
{
_tags = new List<Tag>(tags);
}
#region Implementation of IEnumerable
public IEnumerator<Tag> GetEnumerator()
{
return _tags.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _tags.GetEnumerator();
}
#endregion
#region Implementation of ICollection<Tag>
public void Add(Tag tag)
{
_tags.Add(tag);
}
public void Clear()
{
_tags.Clear();
}
public bool Contains(Tag tag)
{
return _tags.Contains(tag);
}
public void CopyTo(Tag[] array, int arrayIndex)
{
_tags.CopyTo(array, arrayIndex);
}
public bool Remove(Tag tag)
{
return _tags.Remove(tag);
}
public int Count
{
get { return _tags.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
#endregion
#region Implementation of IList<Tag>
public int IndexOf(Tag tag)
{
return _tags.IndexOf(tag);
}
public void Insert(int index, Tag tag)
{
_tags.Insert(index, tag);
}
public void RemoveAt(int index)
{
_tags.RemoveAt(index);
}
public Tag this[int index]
{
get { return _tags[index]; }
set { _tags[index] = value; }
}
#endregion
}
Throw this HtmlHelperExtension.cs file in your project, then just use:
<%= Html.EditorForMany(t => t.Tags) %>
You may also may specify a template for the individual items:
<%= Html.EditorForMany(t => t.Tags, "MySingularTagTemplate") %>
Use the attribute [UIHint("Tags")] then create a display template called Tags.ascx in the DisplayTemplates folder.
class MyModel
{
[UIHint("Tags")]
IList<Tag> Tags { get; protected set; }
}
And in the file Tags.ascx
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Tag>>" %>
<!-- put your Model code here ->
Works for me
I had the same problem as you :-/ but found this useful post which gives you 4 different options to solve the problem :-):
http://blogs.msdn.com/b/stuartleeks/archive/2010/04/01/collections-and-asp-net-mvc-templated-helpers-part-4.aspx
This is also interesting (more or less same solution as one of the solutions in the previous link - but interesting):
http://weblogs.asp.net/rashid/archive/2010/02/09/asp-net-mvc-complex-object-modelmetadata-issue.aspx