views:

378

answers:

4

Hi,

I've been experimenting with ASP.NET MVC and following this tutorial to create the basic task list application. I've gotten it running fine, everything is working although the video is in VB and I had some trouble getting it "converted" to C# but muddled through thanks to the codesample.

Now, to further my knowledge I've decided to make a small modification to the system. I want to change the Index page so as to display "My Tasks" in red if all tasks are complete, and "My Tasks" in green if there are any incomplete tasks.

I've added the following function to HomeController.cs:

    public bool Uncomplete()
    {
        bool AnyLeft = false;
        var tasks = from t in db.Tasks orderby t.EntryDate descending select t;
        foreach (Task match in tasks)
        {
            if (match.IsCompleted == false)
            {
                AnyLeft = true;
            }
        }

        return AnyLeft;
    }

I then modified the Index() ActionResult to look like this:

    public ActionResult Index()
    {
        bool AnyLeft = Uncomplete();
        var tasks = from t in db.Tasks orderby t.EntryDate descending select t;
        return View(tasks.ToList());
    }

With my final intent to use the following code in Index.aspx:

<% if (AnyLeft == false)
   { %>
    <h1 class="green">My Tasks</h1>
<% }
   else
   { %>
    <h1 class="red">My Tasks</h1>
<% } %>

However, I can't figure out how to make Index.aspx "aware" of AnyLeft having a value of true or false. I tried

return View(tasks.ToList(), AnyLeft);

But that throws errors that I can't quite decipher. I have a feeling I'm going about things "the wrong way" but I can't figure it out.

Cheers, Rob

+1  A: 

ViewData["Anyleft"]=Anyleft;

zsharp
Thanks for the input man! -Rob
Rob Burke
+3  A: 

Use this in the controller:

public ActionResult Index()
{
    ViewData["AnyLeft"] = Uncomplete();
    var tasks = from t in db.Tasks orderby t.EntryDate descending select t;
    return View(tasks.ToList());
}

And in the view:

<% if (!(bool)ViewData["AnyLeft"])
   { %>
    <h1 class="green">My Tasks</h1>
<% }
   else
   { %>
    <h1 class="red">My Tasks</h1>
<% } %>
Mehrdad Afshari
Awesome man, worked perfectly! Cheers -Rob
Rob Burke
+1  A: 

Hi Rob,

May I offer a little (hopefully helpful) advice on your Uncomplete method:

public bool Uncomplete()
{
    bool AnyLeft = false;

    var tasks = from t in db.Tasks 
        where !t.IsCompleted // or you could use t.IsCompleted == false
        orderby t.EntryDate descending select t;

    AnyLeft = tasks.Any;

    return AnyLeft;
}

Basically, I've made a couple of (minor) changes based on your original usage:

  1. Firstly, I've added a where clause into the query - this will limit the results to only those we're interested in.
  2. Using .Any will basically only fetch the first record from the database, rather than iterating over the entire record set - this is more efficient even than .Count.

If however you need to do other processing, and so do need to loop over the set, you could perform the loop like this:

    foreach (Task match in tasks)
    {
        if (!match.IsCompleted)
        {
            AnyLeft = true;
            break;
        }
    }

As you don't care how many unfinished tasks there are, there is no point in iterating over the entire set once you've found the first incomplete task, so calling break once you've set AnyLeft will stop further processing of the foreach loop.

I hope that helps.

Zhaph - Ben Duguid
+2  A: 

I would recommend a bit of refactoring combining Zhaph - Ben Duguid's linq with an extension method. like this:

public static class TaskExtensions {
    public static bool Uncomplete(this IEnumerable<Task> tasks) {
     return (from t in tasks where !t.IsCompleted select t).Any();
    }
}

now you can do this in the view:

<h1 class="<%= (tasks.Uncomplete()) ? "Red" : "Green" %>">My Tasks</h1>
Mike Glenn