tags:

views:

1998

answers:

5

I have a IList<Tag> 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 DisplayFor or EditorFor? Usage:

Model

class MyModel 
{
    IList<Tag> Tags { get; protected set; }
}

View

<%= Html.EditorFor(t => t.Tags) %>

edit I know I can do this, but its not what I want to do.

<%= Html.EditorFor(t => t.Tags, "TagList") %>
A: 

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!

takepara
I don't want to iterate it. I am building a StackOverflow like text box for picking tags.
Daniel A. White
This is not a solution, but a diversion from the problem
burnt_hand
+4  A: 

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
}
Jeff French
Now that is pretty slick +1
Dr. Zim
I thought they create Generics just to avoid this :)
Eduardo Molteni
+6  A: 

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

burnt_hand
That was for the display template, but it should work for the Editor template as well
burnt_hand
And you will need to add "using System.ComponentModel.DataAnnotations;"
burnt_hand
+2  A: 

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;}
}
Thomasz
A: 

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

lasseespeholt