Caverman
Caverman

Reputation: 3739

Not able to see ViewModel property in View?

I'm still trying to get my head wrapped around using ViewModels and IEnumerable/List as properties. I'm obviously missing something that is not allowing me to see my IEnumerable in my View.

What I'm ultimately trying to do is have a view that will show a list of unassigned users not assigned to a Group (called Patrols in this case and would have PatrolId=0). The table will have a checkbox next to each member. Above that table will be a DropDownList of the available Patrols. The Admin will come to the page to see those that aren't assigned, select a Patrol from the DDL at the top, check the users he want's to assign to that Patrol, and then submit the form that will pass the PatrolID from the DDL and find all the selected members in order to update their record with that PatrolId.

In the View below when I go to loop through the Scout property, I would assume I would be able to use Model.Scout in this part in order to loop through and write out all the members in that IEnumerable.

@for (var i = 0; i < Model.Count(); i++)

However, when I try to use intellisense to see the Scout property when using the Model, I don't see the property. In addition to that I would think I would need to first check the Scout property to see if there is a count before I write out all the rows. Again, I can't see the Scout property in order to check it's count.

ViewModel

public class PatrolMemberViewModel
{
        [Key]
        public int MemberId { get; set; }

        public int PatrolId { get; set; }

        [Display(Name = "First Name")]
        public string FirstName { get; set; }

        [Display(Name = "Last Name")]
        public string LastName { get; set; }

        [Display(Name = "Phone")]
        public string PhonePrimary { get; set; }

        [Display(Name = "Email")]
        public string EmailPrimary { get; set; }

        public bool IsSelected { get; set; }
}

public class PatrolUnassignedViewModel
{
        public SelectList Patrols { get; set; }

        public IEnumerable<PatrolMemberViewModel> Scout { get; set; }
}

Controller

// GET: 
public ViewResult Unassigned()
{
    PatrolUnassignedViewModel unassinged = new PatrolUnassignedViewModel();
    unassinged.Patrols = new SelectList(repository.SelectAllPatrols());
    unassinged.Scout = repository.SelectAllUnassigned();
            
    return View(unassinged);
}

Repository

public IEnumerable<PatrolMemberViewModel> SelectAllUnassigned()
{
            using (DataContext db = new DataContext())
            {
                var results = (from p in db.Person
                               where p.IsActive == true
                               && p.IsScout == true
                               && p.PatrolId == 0
                               select new PatrolMemberViewModel
                               {
                                   MemberId = p.PID,
                                   FirstName = p.FirstName ?? string.Empty,
                                   LastName = p.LastName ?? string.Empty,
                                   EmailPrimary = p.EmailPrimary ?? string.Empty,
                                   PhonePrimary = p.PhonePrimary ?? string.Empty,
                                   PatrolId = p.PatrolId,
                                   IsSelected = false
                               }
                                ).OrderBy(o => o.LastName).ThenBy(o => o.FirstName).ToList();

                return results;
            }
}

public IEnumerable<PatrolName> SelectAllPatrols()
{
    return db.PatrolNames;
}

View

@model IList<ProjectName.ViewModels.PatrolUnassignedViewModel>

@{
    ViewBag.Title = "Unassigned";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Patrols</h2>
<h4>Assign Scouts to a Patrol.</h4>


@using (Html.BeginForm("Update", "Patrol", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(false, "", new { @class = "alert alert-danger" })

    <table class="table table-bordered table-striped table-hover table-condensed tbackground">
        <tr>
            <th class="text-center">

            </th>
            <th class="text-center">
                First Name
            </th>
            <th class="text-center">
                Last Name
            </th>
            <th class="text-center">
                Email
            </th>
            <th class="text-center">
                Phone
            </th>
        </tr>
    
        @for (var i = 0; i < Model.Count(); i++)
        {
        <tr>
            <td class="text-center">
                @Html.CheckBoxFor(m => m[i].IsSelected)
            </td>
            <td>
                @Html.DisplayFor(m => m[i].FirstName)
            </td>
            <td>
                @Html.DisplayFor(m => m[i].LastName)
            </td>
            <td>
                <a href="mailto:@Model[i].EmailPrimary">@Model[i].EmailPrimary</a>
            </td>
            <td class="text-center">
                @Html.DisplayFor(m => m[i].PhonePrimary)
            </td>
        </tr>
        }

    </table>
    
    <div class="control-wrapper">
        <input type="submit" id="btnSubmit" value="Assign Scouts" class="btn btn-success" />
    </div>
}
<p>&nbsp;</p>

Upvotes: 0

Views: 266

Answers (2)

Shyju
Shyju

Reputation: 218892

From your GET action method, you are passing a single object of PatrolUnassignedViewModel. But your view is bound to a collection of PatrolUnassignedViewModel. So change your view to be like

@model PatrolUnassignedViewModel

Now you can use the Model.Scout property which is a collection.

@model PatrolUnassignedViewModel
<h2>Total : @Model.Scout.Count()</h2>
@foreach(var item in Model.Scout)
{
   <label>@item.FirstName</label>
}

Upvotes: 1

James Dev
James Dev

Reputation: 3009

You controller is returning a single instance of class PatrolUnassignedViewModel

    public ViewResult Unassigned()
    {
        PatrolUnassignedViewModel unassinged = new PatrolUnassignedViewModel();
        unassinged.Patrols = new SelectList(repository.SelectAllPatrols());
        unassinged.Scout = repository.SelectAllUnassigned();
        return View(unassinged);
    }

Your view is expecting an IList

@model IList<ProjectName.ViewModels.PatrolUnassignedViewModel>

When it should be expecting

@model ProjectName.ViewModels.PatrolUnassignedViewModel

Your scout is an IEnumerable so doesn't have a count method so should be

public IList<PatrolMemberViewModel> Scout { get; set; }
public IList<PatrolMemberViewModel> SelectAllUnassigned()
{
}

You should be doing your loop like this

    @for (var i = 0; i < Model.Scout.Count(); i++)
    {
    <tr>
        <td class="text-center">
            @Html.CheckBoxFor(m => m.Scout[i].IsSelected)
        </td>
        <td>
            @Html.DisplayFor(m => m.Scout[i].FirstName)
        </td>
        <td>
            @Html.DisplayFor(m => m.Scout[i].LastName)
        </td>
        <td>
            <a href="mailto:@Model.Scout[i].EmailPrimary">@Model.Scout[i].EmailPrimary</a>
        </td>
        <td class="text-center">
            @Html.DisplayFor(m => m.Scout[i].PhonePrimary)
        </td>
    </tr>
    }

Am I missing something here?

Upvotes: 4

Related Questions