Notifying Students in Courses - Strategically
This smells of a message chain and violates the Law of Demeter (principle of least knowledge):

treeListViewModel.Courses[i].Students[DataNotificationList[n]].ExecuteStrategy(hasError());


Your caller very like doesn't care of the exact internal workings of a course - it should just dispatch the notifications and see if it succeeded. So a Course should probably get a method like bool NotifyStudent(int studentId, bool hasError).
When you use expressions like DataNotificationList[n] in several places then it is usually better to put it in a local variable which expresses the meaning of it and also makes the code shorter, for example like this: int studentId = DataNotificationList[n]; 
If you don't actually need the index then foreach will usually suffice and is shorter.




So in total your refactored code could look like this:

    foreach (int studentId in DataNotificationList)
    {
        foreach (Course course in treeListViewModel.Courses)
        {
            if (course.NotifyStudent(studentId, hasError()))
            {
                break;
            }
        }
    }


or if you want to go with a bit more LINQ:

    foreach (int studentId in DataNotificationList)
    {
        var course = treeListViewModel.Courses
                        .FirstOrDefault(c =&gt; c.NotifyStudent(studentId, hasError()));
        // could log something here and maybe raise an event handler
        // to say that a student in a course has been notified
    }


The NotifyStudent method in the course is responsible to check if the student exists in the course and return true once it has executed the strategy. It is totally encapsulated in the course and the caller doesn't have to know about any internals.