using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using SchoolSample.Common;
using SchoolSample.EntityModel;
using SchoolSample.WCFService.SchoolService;
namespace SchoolSample.Model
{
[Export(typeof(ISchoolModel))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class SchoolModel : ISchoolModel
{
#region "Private Data"
private ISchoolServiceClient _proxy;
private ActionQueue _actionQueue;
private Exception _lastError;
#endregion "Private Data"
#region "Constructor"
public SchoolModel()
: this(SchoolServiceClient.Instance)
{
}
public SchoolModel(ISchoolServiceClient schoolServiceClient)
{
_proxy = schoolServiceClient;
// Set up event handling
_proxy.PropertyChanged += _proxy_PropertyChanged;
_actionQueue = new ActionQueue();
}
#endregion "Constructor"
#region "ISchoolModel Interface (Data Retrieval) implementation"
public void GetStudentsAsync(string includeOption, string screenName)
{
_proxy.BeginGetStudents(includeOption, BeginGetStudentsComplete, screenName);
_proxy.IncrementCallCount();
}
public void GetStudentByIdAsync(int studentId)
{
_proxy.BeginGetStudentById(studentId, BeginGetStudentByIdComplete, null);
_proxy.IncrementCallCount();
}
public void GetInstructorsAsync(string includeOption, string screenName)
{
_proxy.BeginGetInstructors(includeOption, BeginGetInstructorsComplete, screenName);
_proxy.IncrementCallCount();
}
public void GetInstructorByIdAsync(int instructorId)
{
_proxy.BeginGetInstructorById(instructorId, BeginGetInstructorByIdComplete, null);
_proxy.IncrementCallCount();
}
public void GetCoursesAsync(string screenName)
{
_proxy.BeginGetCourses(BeginGetCoursesComplete, screenName);
_proxy.IncrementCallCount();
}
public void GetCourseByIdAsync(int courseId)
{
_proxy.BeginGetCourseById(courseId, BeginGetCourseByIdComplete, null);
_proxy.IncrementCallCount();
}
public event EventHandler<ResultsArgs<Student>> GetStudentsCompleted;
public event EventHandler<ResultArgs<Student>> GetStudentByIdCompleted;
public event EventHandler<ResultsArgs<Instructor>> GetInstructorsCompleted;
public event EventHandler<ResultArgs<Instructor>> GetInstructorByIdCompleted;
public event EventHandler<ResultsArgs<Course>> GetCoursesCompleted;
public event EventHandler<ResultArgs<Course>> GetCourseByIdCompleted;
#endregion "ISchoolModel Interface (Data Retrieval) implementation"
#region "ISchoolModel Interface (Data Cache) implementation"
public ObservableCollection<Student> StudentsList
{
get { return _studentsList; }
set
{
if (!ReferenceEquals(_studentsList, value))
{
if (_studentsList != null)
{
_studentsList.CollectionChanged -= _studentsList_CollectionChanged;
foreach (var student in _studentsList)
{
((INotifyPropertyChanged)student).PropertyChanged -= EntityModel_PropertyChanged;
}
}
_studentsList = value;
if (_studentsList != null)
{
_studentsList.CollectionChanged += _studentsList_CollectionChanged;
foreach (var student in _studentsList)
{
((INotifyPropertyChanged)student).PropertyChanged += EntityModel_PropertyChanged;
}
}
ReCalculateStudentsListHasChanges();
}
}
}
private ObservableCollection<Student> _studentsList;
public Student CurrentStudent
{
get { return _currentStudent; }
set
{
if (!ReferenceEquals(_currentStudent, value))
{
if (_currentStudent != null)
{
((INotifyPropertyChanged)_currentStudent).PropertyChanged -= EntityModel_PropertyChanged;
}
_currentStudent = value;
if (_currentStudent != null)
{
((INotifyPropertyChanged)_currentStudent).PropertyChanged += EntityModel_PropertyChanged;
}
ReCalculateCurrentStudentHasChanges();
}
}
}
private Student _currentStudent;
public ObservableCollection<Instructor> InstructorsList
{
get { return _instructorsList; }
set
{
if (!ReferenceEquals(_instructorsList, value))
{
if (_instructorsList != null)
{
_instructorsList.CollectionChanged -= _instructorsList_CollectionChanged;
foreach (var instructor in _instructorsList)
{
((INotifyPropertyChanged)instructor).PropertyChanged -= EntityModel_PropertyChanged;
}
}
_instructorsList = value;
if (_instructorsList != null)
{
_instructorsList.CollectionChanged += _instructorsList_CollectionChanged;
foreach (var instructor in _instructorsList)
{
((INotifyPropertyChanged)instructor).PropertyChanged += EntityModel_PropertyChanged;
}
}
ReCalculateInstructorsListHasChanges();
}
}
}
private ObservableCollection<Instructor> _instructorsList;
public Instructor CurrentInstructor
{
get { return _currentInstructor; }
set
{
if (!ReferenceEquals(_currentInstructor, value))
{
if (_currentInstructor != null)
{
((INotifyPropertyChanged)_currentInstructor).PropertyChanged -= EntityModel_PropertyChanged;
}
_currentInstructor = value;
if (_currentInstructor != null)
{
((INotifyPropertyChanged)_currentInstructor).PropertyChanged += EntityModel_PropertyChanged;
}
ReCalculateCurrentInstructorHasChanges();
}
}
}
private Instructor _currentInstructor;
public ObservableCollection<Course> CoursesList
{
get { return _coursesList; }
set
{
if (!ReferenceEquals(_coursesList, value))
{
if (_coursesList != null)
{
_coursesList.CollectionChanged -= _coursesList_CollectionChanged;
foreach (var course in _coursesList)
{
((INotifyPropertyChanged)course).PropertyChanged -= EntityModel_PropertyChanged;
if (course.Enrollments != null)
{
course.Enrollments.CollectionChanged -= Enrollments_CollectionChanged;
foreach (var enrollment in course.Enrollments)
{
((INotifyPropertyChanged)enrollment).PropertyChanged -= EntityModel_PropertyChanged;
}
}
}
}
_coursesList = value;
if (_coursesList != null)
{
_coursesList.CollectionChanged += _coursesList_CollectionChanged;
foreach (var course in _coursesList)
{
((INotifyPropertyChanged)course).PropertyChanged += EntityModel_PropertyChanged;
if (course.Enrollments != null)
{
course.Enrollments.CollectionChanged += Enrollments_CollectionChanged;
foreach (var enrollment in course.Enrollments)
{
((INotifyPropertyChanged)enrollment).PropertyChanged += EntityModel_PropertyChanged;
}
}
}
}
ReCalculateCoursesListHasChanges();
}
}
}
private ObservableCollection<Course> _coursesList;
public Course CurrentCourse
{
get { return _currentCourse; }
set
{
if (!ReferenceEquals(_currentCourse, value))
{
if (_currentCourse != null)
{
((INotifyPropertyChanged)_currentCourse).PropertyChanged -= EntityModel_PropertyChanged;
if (_currentCourse.Enrollments != null)
{
_currentCourse.Enrollments.CollectionChanged -= Enrollments_CollectionChanged;
foreach (var enrollment in _currentCourse.Enrollments)
{
((INotifyPropertyChanged)enrollment).PropertyChanged -= EntityModel_PropertyChanged;
}
}
}
_currentCourse = value;
if (_currentCourse != null)
{
((INotifyPropertyChanged)_currentCourse).PropertyChanged += EntityModel_PropertyChanged;
if (_currentCourse.Enrollments != null)
{
_currentCourse.Enrollments.CollectionChanged += Enrollments_CollectionChanged;
foreach (var enrollment in _currentCourse.Enrollments)
{
((INotifyPropertyChanged)enrollment).PropertyChanged += EntityModel_PropertyChanged;
}
}
}
ReCalculateCurrentCourseHasChanges();
}
}
}
private Course _currentCourse;
#endregion "ISchoolModel Interface (Data Cache) implementation"
#region "ISchoolModel Interface (Data Status) implementation"
public bool StudentsListHasChanges
{
get { return _studentsListHasChanges; }
private set
{
if (_studentsListHasChanges != value)
{
_studentsListHasChanges = value;
OnPropertyChanged("StudentsListHasChanges");
}
}
}
private bool _studentsListHasChanges;
public bool CurrentStudentHasChanges
{
get { return _currentStudentHasChanges; }
private set
{
if (_currentStudentHasChanges != value)
{
_currentStudentHasChanges = value;
OnPropertyChanged("CurrentStudentHasChanges");
}
}
}
private bool _currentStudentHasChanges;
public bool InstructorsListHasChanges
{
get { return _instructorsListHasChanges; }
private set
{
if (_instructorsListHasChanges != value)
{
_instructorsListHasChanges = value;
OnPropertyChanged("InstructorsListHasChanges");
}
}
}
private bool _instructorsListHasChanges;
public bool CurrentInstructorHasChanges
{
get { return _currentInstructorHasChanges; }
private set
{
if (_currentInstructorHasChanges != value)
{
_currentInstructorHasChanges = value;
OnPropertyChanged("CurrentInstructorHasChanges");
}
}
}
private bool _currentInstructorHasChanges;
public bool CoursesListHasChanges
{
get { return _coursesListHasChanges; }
private set
{
if (_coursesListHasChanges != value)
{
_coursesListHasChanges = value;
OnPropertyChanged("CoursesListHasChanges");
}
}
}
private bool _coursesListHasChanges;
public bool CurrentCourseHasChanges
{
get { return _currentCourseHasChanges; }
private set
{
if (_currentCourseHasChanges != value)
{
_currentCourseHasChanges = value;
OnPropertyChanged("CurrentCourseHasChanges");
}
}
}
private bool _currentCourseHasChanges;
/// <summary>
/// True if at least one call is
/// in progress; otherwise, false
/// </summary>
public Boolean IsBusy
{
get { return _isBusy; }
private set
{
if (_isBusy != value)
{
_isBusy = value;
OnPropertyChanged("IsBusy");
}
}
}
private Boolean _isBusy;
#endregion "ISchoolModel Interface (Data Status) implementation"
#region "ISchoolModel Interface (Update and Rollback of Entity List) implementation"
/// <summary>
/// If allItems is true, all items from the StudentsList have
/// their changes saved; otherwise, only CurrentStudent from
/// the StudentsList has its changes saved.
/// </summary>
/// <param name="allItems"></param>
public void SaveStudentChangesAsync(bool allItems = true)
{
if (allItems)
{
if (StudentsList != null && StudentsListHasChanges)
{
// save changes for all items from the StudentsList
foreach (var student in StudentsList.Where(n => n.ObjectGraphHasChanges()))
{
var totalSize = student.EstimateObjectGraphSize();
var changeSize = student.EstimateObjectGraphChangeSize();
// if the optimized entity object graph is less than 70%
// of the original, call GetObjectGraphChanges()
var currentStudent = changeSize < (totalSize*0.7)
? (Student) student.GetObjectGraphChanges()
: student;
_actionQueue.Add(
n => _proxy.BeginUpdateStudent(
currentStudent,
BeginUpdateStudentComplete,
currentStudent.PersonId));
}
// start save changes for the first student
if (_actionQueue.BeginOneAction()) _proxy.IncrementCallCount();
}
}
else
{
if (CurrentStudent != null && StudentsList != null && CurrentStudentHasChanges)
{
// save changes for only CurrentStudent from the StudentsList
var currentStudent = StudentsList
.FirstOrDefault(n => n.PersonId == CurrentStudent.PersonId);
if (currentStudent != null)
{
var totalSize = currentStudent.EstimateObjectGraphSize();
var changeSize = currentStudent.EstimateObjectGraphChangeSize();
// if the optimized entity object graph is less than 70%
// of the original, call GetObjectGraphChanges()
currentStudent = changeSize < (totalSize*0.7)
? (Student) currentStudent.GetObjectGraphChanges()
: currentStudent;
_actionQueue.Add(
n => _proxy.BeginUpdateStudent(
currentStudent,
BeginUpdateStudentComplete,
currentStudent.PersonId));
// start save changes for the current student
if (_actionQueue.BeginOneAction()) _proxy.IncrementCallCount();
}
}
}
}
/// <summary>
/// If allItems is true, all items from the StudentsList have
/// their changes rejected; otherwise, only CurrentStudent from
/// the StudentsList has its changes rejected.
/// </summary>
/// <param name="allItems"></param>
public void RejectStudentChanges(bool allItems = true)
{
if (allItems)
{
if (StudentsList != null && StudentsListHasChanges)
{
// reject changes for all items from the StudentsList
foreach (var student in StudentsList.Where(n => n.ObjectGraphHasChanges()).ToList())
{
var isAdded = student.ChangeTracker.State == ObjectState.Added;
student.RejectObjectGraphChanges();
// if the State is Added, simply remove it from the StudentsList
if (isAdded) StudentsList.Remove(student);
}
}
}
else
{
if (CurrentStudent != null && StudentsList != null && CurrentStudentHasChanges)
{
// reject changes for only CurrentStudent from the StudentsList
var currentStudent = StudentsList
.FirstOrDefault(n => n.PersonId == CurrentStudent.PersonId);
if (currentStudent != null)
{
var isAdded = currentStudent.ChangeTracker.State == ObjectState.Added;
currentStudent.RejectObjectGraphChanges();
// if the State is Added, simply remove it from the StudentsList
if (isAdded) StudentsList.Remove(currentStudent);
}
}
}
}
/// <summary>
/// If allItems is true, all items from the InstructorsList have
/// their changes saved; otherwise, only CurrentInstructor from
/// the InstructorsList has its changes saved.
/// </summary>
/// <param name="allItems"></param>
public void SaveInstructorChangesAsync(bool allItems = true)
{
if (allItems)
{
if (InstructorsList != null && InstructorsListHasChanges)
{
// save changes for all items from the InstructorsList
foreach (var instructor in InstructorsList.Where(n => n.ObjectGraphHasChanges()))
{
var totalSize = instructor.EstimateObjectGraphSize();
var changeSize = instructor.EstimateObjectGraphChangeSize();
// if the optimized entity object graph is less than 70%
// of the original, call GetObjectGraphChanges()
var currentInstructor = changeSize < (totalSize*0.7)
? (Instructor) instructor.GetObjectGraphChanges()
: instructor;
_actionQueue.Add(
n => _proxy.BeginUpdateInstructor(
currentInstructor,
BeginUpdateInstructorComplete,
currentInstructor.PersonId));
}
// start save changes for the first instructor
if (_actionQueue.BeginOneAction()) _proxy.IncrementCallCount();
}
}
else
{
if (CurrentInstructor != null && InstructorsList != null && CurrentInstructorHasChanges)
{
// save changes for only CurrentInstructor from the InstructorsList
var currentInstructor = InstructorsList
.FirstOrDefault(n => n.PersonId == CurrentInstructor.PersonId);
if (currentInstructor != null)
{
var totalSize = currentInstructor.EstimateObjectGraphSize();
var changeSize = currentInstructor.EstimateObjectGraphChangeSize();
// if the optimized entity object graph is less than 70%
// of the original, call GetObjectGraphChanges()
currentInstructor = changeSize < (totalSize*0.7)
? (Instructor) currentInstructor.GetObjectGraphChanges()
: currentInstructor;
_actionQueue.Add(
n => _proxy.BeginUpdateInstructor(
currentInstructor,
BeginUpdateInstructorComplete,
currentInstructor.PersonId));
// start save changes for the current instructor
if (_actionQueue.BeginOneAction()) _proxy.IncrementCallCount();
}
}
}
}
/// <summary>
/// If allItems is true, all items from the InstructorsList have
/// their changes rejected; otherwise, only CurrentInstructor from
/// the InstructorsList has its changes rejected.
/// </summary>
/// <param name="allItems"></param>
public void RejectInstructorChanges(bool allItems = true)
{
if (allItems)
{
if (InstructorsList != null && InstructorsListHasChanges)
{
// reject changes for all items from the InstructorsList
foreach (var instructor in InstructorsList.Where(n => n.ObjectGraphHasChanges()).ToList())
{
var isAdded = instructor.ChangeTracker.State == ObjectState.Added;
instructor.RejectObjectGraphChanges();
// if the State is Added, simply remove it from the InstructorsList
if (isAdded) InstructorsList.Remove(instructor);
}
}
}
else
{
if (CurrentInstructor != null && InstructorsList != null && CurrentInstructorHasChanges)
{
// reject changes for only CurrentInstructor from the InstructorsList
var currentInstructor = InstructorsList
.FirstOrDefault(n => n.PersonId == CurrentInstructor.PersonId);
if (currentInstructor != null)
{
var isAdded = currentInstructor.ChangeTracker.State == ObjectState.Added;
currentInstructor.RejectObjectGraphChanges();
// if the State is Added, simply remove it from the InstructorsList
if (isAdded) InstructorsList.Remove(currentInstructor);
}
}
}
}
/// <summary>
/// If allItems is true, all items from the CoursesList have
/// their changes saved; otherwise, only CurrentCourse from
/// the CoursesList has its changes saved.
/// </summary>
/// <param name="allItems"></param>
public void SaveCourseChangesAsync(bool allItems = true)
{
if (allItems)
{
if (CoursesList != null && CoursesListHasChanges)
{
// save changes for all items from the CoursesList
foreach (var course in CoursesList.Where(n => n.ObjectGraphHasChanges()))
{
var totalSize = course.EstimateObjectGraphSize();
var changeSize = course.EstimateObjectGraphChangeSize();
// if the optimized entity object graph is less than 70%
// of the original, call GetObjectGraphChanges()
var currentCourse = changeSize < (totalSize*0.7)
? (Course) course.GetObjectGraphChanges()
: course;
_actionQueue.Add(
n => _proxy.BeginUpdateCourse(
currentCourse,
BeginUpdateCourseComplete,
currentCourse.CourseId));
}
// start save changes for the first course in queue
if (_actionQueue.BeginOneAction()) _proxy.IncrementCallCount();
}
}
else
{
if (CurrentCourse != null && CoursesList != null && CurrentCourseHasChanges)
{
// save changes for only CurrentCourse from the CoursesList
var currentCourse = CoursesList.FirstOrDefault(n => n.CourseId == CurrentCourse.CourseId);
if (currentCourse != null)
{
var totalSize = currentCourse.EstimateObjectGraphSize();
var changeSize = currentCourse.EstimateObjectGraphChangeSize();
// if the optimized entity object graph is less than 70%
// of the original, call GetObjectGraphChanges()
currentCourse = changeSize < (totalSize*0.7)
? (Course) currentCourse.GetObjectGraphChanges()
: currentCourse;
_actionQueue.Add(
n => _proxy.BeginUpdateCourse(
currentCourse,
BeginUpdateCourseComplete,
currentCourse.CourseId));
// start save changes for the current course
if (_actionQueue.BeginOneAction()) _proxy.IncrementCallCount();
}
}
}
}
/// <summary>
/// If allItems is true, all items from the CoursesList have
/// their changes rejected; otherwise, only CurrentCourse from
/// the CoursesList has its changes rejected.
/// </summary>
/// <param name="allItems"></param>
public void RejectCourseChanges(bool allItems = true)
{
if (allItems)
{
if (CoursesList != null && CoursesListHasChanges)
{
// reject changes for all items from the CoursesList
foreach (var course in CoursesList.Where(n => n.ObjectGraphHasChanges()).ToList())
{
var isAdded = course.ChangeTracker.State == ObjectState.Added;
course.RejectObjectGraphChanges();
// if the State is Added, simply remove it from the CoursesList
if (isAdded) CoursesList.Remove(course);
}
}
}
else
{
if (CurrentCourse != null && CoursesList != null && CurrentCourseHasChanges)
{
// reject changes for only CurrentCourse from the CoursesList
var currentCourse = CoursesList.FirstOrDefault(n => n.CourseId == CurrentCourse.CourseId);
if (currentCourse != null)
{
var isAdded = currentCourse.ChangeTracker.State == ObjectState.Added;
currentCourse.RejectObjectGraphChanges();
// if the State is Added, simply remove it from the CoursesList
if (isAdded) CoursesList.Remove(currentCourse);
}
}
}
}
public event EventHandler<ResultArgs<string>> SaveStudentChangesCompleted;
public event EventHandler<ResultArgs<string>> SaveInstructorChangesCompleted;
public event EventHandler<ResultArgs<string>> SaveCourseChangesCompleted;
#endregion "ISchoolModel Interface (Update and Rollback of Entity List) implementation"
#region "ISchoolModel Interface (Error Handling) implementation"
public Exception GetLastError()
{
return _lastError;
}
public void ClearLastError()
{
_lastError = null;
}
public bool AllowMultipleErrors { get; set; }
#endregion "ISchoolModel Interface (Error Handling) implementation"
#region "INotifyPropertyChanged Interface implementation"
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion "INotifyPropertyChanged Interface implementation"
#region "Private Methods"
/// <summary>
/// CollectionChanged Event handler for _studentsList
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void _studentsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Student newItem in e.NewItems)
((INotifyPropertyChanged)newItem).PropertyChanged += EntityModel_PropertyChanged;
}
if (e.OldItems != null)
{
foreach (Student oldItem in e.OldItems)
((INotifyPropertyChanged)oldItem).PropertyChanged -= EntityModel_PropertyChanged;
}
ReCalculateStudentsListHasChanges();
}
/// <summary>
/// CollectionChanged Event handler for _instructorsList
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void _instructorsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Instructor newItem in e.NewItems)
((INotifyPropertyChanged)newItem).PropertyChanged += EntityModel_PropertyChanged;
}
if (e.OldItems != null)
{
foreach (Instructor oldItem in e.OldItems)
((INotifyPropertyChanged)oldItem).PropertyChanged -= EntityModel_PropertyChanged;
}
ReCalculateInstructorsListHasChanges();
}
/// <summary>
/// CollectionChanged Event handler for _coursesList
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void _coursesList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Course newItem in e.NewItems)
{
((INotifyPropertyChanged)newItem).PropertyChanged += EntityModel_PropertyChanged;
if (newItem.Enrollments != null)
{
newItem.Enrollments.CollectionChanged += Enrollments_CollectionChanged;
foreach (Enrollment item in newItem.Enrollments)
((INotifyPropertyChanged)item).PropertyChanged += EntityModel_PropertyChanged;
}
}
}
if (e.OldItems != null)
{
foreach (Course oldItem in e.OldItems)
{
((INotifyPropertyChanged)oldItem).PropertyChanged -= EntityModel_PropertyChanged;
if (oldItem.Enrollments != null)
{
oldItem.Enrollments.CollectionChanged -= Enrollments_CollectionChanged;
foreach (Enrollment item in oldItem.Enrollments)
((INotifyPropertyChanged)item).PropertyChanged -= EntityModel_PropertyChanged;
}
}
}
ReCalculateCoursesListHasChanges();
}
/// <summary>
/// CollectionChanged Event handler for Enrollments
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Enrollments_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Enrollment item in e.NewItems)
((INotifyPropertyChanged)item).PropertyChanged += EntityModel_PropertyChanged;
}
if (e.OldItems != null)
{
foreach (Enrollment item in e.OldItems)
((INotifyPropertyChanged)item).PropertyChanged -= EntityModel_PropertyChanged;
}
}
/// <summary>
/// Event handler for PropertyChanged
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void EntityModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals("HasChanges"))
{
if (sender is Student)
{
ReCalculateStudentsListHasChanges();
ReCalculateCurrentStudentHasChanges();
}
else if (sender is Instructor)
{
ReCalculateInstructorsListHasChanges();
ReCalculateCurrentInstructorHasChanges();
}
else if (sender is Course || sender is Enrollment)
{
ReCalculateCoursesListHasChanges();
ReCalculateCurrentCourseHasChanges();
}
else
{
throw new NotImplementedException();
}
}
}
/// <summary>
/// Re-calculate whether StudentsList has any changes
/// </summary>
private void ReCalculateStudentsListHasChanges()
{
// re-calculate StudentsListHasChanges
StudentsListHasChanges = StudentsList != null
&& StudentsList.Any(n => n.ObjectGraphHasChanges());
}
/// <summary>
/// Re-calculate whether CurrentStudent has changes
/// </summary>
private void ReCalculateCurrentStudentHasChanges()
{
// re-calculate CurrentStudentHasChanges
CurrentStudentHasChanges = CurrentStudent != null
&& CurrentStudent.ObjectGraphHasChanges();
}
/// <summary>
/// Re-calculate whether InstructorsList has any changes
/// </summary>
private void ReCalculateInstructorsListHasChanges()
{
// re-calculate InstructorsListHasChanges
InstructorsListHasChanges = InstructorsList != null
&& InstructorsList.Any(n => n.ObjectGraphHasChanges());
}
/// <summary>
/// Re-calculate whether CurrentInstructor has changes
/// </summary>
private void ReCalculateCurrentInstructorHasChanges()
{
// re-calculate CurrentInstructorHasChanges
CurrentInstructorHasChanges = CurrentInstructor != null
&& CurrentInstructor.ObjectGraphHasChanges();
}
/// <summary>
/// Re-calculate whether CoursesList has any changes
/// </summary>
private void ReCalculateCoursesListHasChanges()
{
// re-calculate CoursesListHasChanges
CoursesListHasChanges = CoursesList != null
&& CoursesList.Any(n => n.ObjectGraphHasChanges());
}
/// <summary>
/// Re-calculate whether CurrentCourse has changes
/// </summary>
private void ReCalculateCurrentCourseHasChanges()
{
// re-calculate CurrentCourseHasChanges
CurrentCourseHasChanges = CurrentCourse != null
&& CurrentCourse.ObjectGraphHasChanges();
}
/// <summary>
/// Event handler for PropertyChanged
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void _proxy_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals("ActiveCallCount"))
{
// re-calculate IsBusy
IsBusy = (_proxy.ActiveCallCount != 0);
}
}
/// <summary>
/// AsyncCallback for BeginGetStudents
/// </summary>
/// <param name="result"></param>
private void BeginGetStudentsComplete(IAsyncResult result)
{
ThreadHelper.BeginInvokeOnUIThread(
delegate
{
_proxy.DecrementCallCount();
try
{
// get the return values
var students = _proxy.EndGetStudents(result);
if (GetStudentsCompleted != null)
{
GetStudentsCompleted(this, new ResultsArgs<Student>(students, null, false, result.AsyncState));
}
}
catch (Exception ex)
{
if (GetStudentsCompleted != null && (_lastError == null || AllowMultipleErrors))
{
GetStudentsCompleted(this, new ResultsArgs<Student>(null, ex, true, result.AsyncState));
}
_lastError = ex;
}
});
}
/// <summary>
/// AsyncCallback for BeginGetStudentById
/// </summary>
/// <param name="result"></param>
private void BeginGetStudentByIdComplete(IAsyncResult result)
{
ThreadHelper.BeginInvokeOnUIThread(
delegate
{
_proxy.DecrementCallCount();
try
{
// get the return values
var student = _proxy.EndGetStudentById(result);
if (GetStudentByIdCompleted != null)
{
GetStudentByIdCompleted(this, new ResultArgs<Student>(student, null, false, result.AsyncState));
}
}
catch (Exception ex)
{
if (GetStudentByIdCompleted != null && (_lastError == null || AllowMultipleErrors))
{
GetStudentByIdCompleted(this, new ResultArgs<Student>(null, ex, true, result.AsyncState));
}
_lastError = ex;
}
});
}
/// <summary>
/// AsyncCallback for BeginGetInstructors
/// </summary>
/// <param name="result"></param>
private void BeginGetInstructorsComplete(IAsyncResult result)
{
ThreadHelper.BeginInvokeOnUIThread(
delegate
{
_proxy.DecrementCallCount();
try
{
// get the return values
var instructors = _proxy.EndGetInstructors(result);
if (GetInstructorsCompleted != null)
{
GetInstructorsCompleted(this, new ResultsArgs<Instructor>(instructors, null, false, result.AsyncState));
}
}
catch (Exception ex)
{
if (GetInstructorsCompleted != null && (_lastError == null || AllowMultipleErrors))
{
GetInstructorsCompleted(this, new ResultsArgs<Instructor>(null, ex, true, result.AsyncState));
}
_lastError = ex;
}
});
}
/// <summary>
/// AsyncCallback for BeginGetInstructorById
/// </summary>
/// <param name="result"></param>
private void BeginGetInstructorByIdComplete(IAsyncResult result)
{
ThreadHelper.BeginInvokeOnUIThread(
delegate
{
_proxy.DecrementCallCount();
try
{
// get the return values
var instructor = _proxy.EndGetInstructorById(result);
if (GetInstructorByIdCompleted != null)
{
GetInstructorByIdCompleted(this, new ResultArgs<Instructor>(instructor, null, false, result.AsyncState));
}
}
catch (Exception ex)
{
if (GetInstructorByIdCompleted != null && (_lastError == null || AllowMultipleErrors))
{
GetInstructorByIdCompleted(this, new ResultArgs<Instructor>(null, ex, true, result.AsyncState));
}
_lastError = ex;
}
});
}
/// <summary>
/// AsyncCallback for BeginGetCourses
/// </summary>
/// <param name="result"></param>
private void BeginGetCoursesComplete(IAsyncResult result)
{
ThreadHelper.BeginInvokeOnUIThread(
delegate
{
_proxy.DecrementCallCount();
try
{
// get the return values
var courses = _proxy.EndGetCourses(result);
if (GetCoursesCompleted != null)
{
GetCoursesCompleted(this, new ResultsArgs<Course>(courses, null, false, result.AsyncState));
}
}
catch (Exception ex)
{
if (GetCoursesCompleted != null && (_lastError == null || AllowMultipleErrors))
{
GetCoursesCompleted(this, new ResultsArgs<Course>(null, ex, true, result.AsyncState));
}
_lastError = ex;
}
});
}
/// <summary>
/// AsyncCallback for BeginGetCourseById
/// </summary>
/// <param name="result"></param>
private void BeginGetCourseByIdComplete(IAsyncResult result)
{
ThreadHelper.BeginInvokeOnUIThread(
delegate
{
_proxy.DecrementCallCount();
try
{
// get the return values
var course = _proxy.EndGetCourseById(result);
if (GetCourseByIdCompleted != null)
{
GetCourseByIdCompleted(this, new ResultArgs<Course>(course, null, false, result.AsyncState));
}
}
catch (Exception ex)
{
if (GetCourseByIdCompleted != null && (_lastError == null || AllowMultipleErrors))
{
GetCourseByIdCompleted(this, new ResultArgs<Course>(null, ex, true, result.AsyncState));
}
_lastError = ex;
}
});
}
/// <summary>
/// AsyncCallback for BeginUpdateStudent
/// </summary>
/// <param name="result"></param>
private void BeginUpdateStudentComplete(IAsyncResult result)
{
ThreadHelper.BeginInvokeOnUIThread(
delegate
{
try
{
// get the return values
var returnList = _proxy.EndUpdateStudent(result);
// returnList[0] could be a warning message
var warningMessage = returnList[0] as string;
// returnList[1] is the updated student Id
var updatedStudentId = Convert.ToInt32(returnList[1]);
// get the studentId for the student that finished saving changes
var studentId = Convert.ToInt32(result.AsyncState);
var student = StudentsList.Single(n => n.PersonId == studentId);
// update the student Id if the student State is Added
if (student.ChangeTracker.State == ObjectState.Added)
student.PersonId = updatedStudentId;
if (string.IsNullOrEmpty(warningMessage))
{
var isDeleted = student.ChangeTracker.State == ObjectState.Deleted;
// if there is no error or warning message, call AcceptObjectGraphChanges() first
student.AcceptObjectGraphChanges();
// if State is Deleted, remove the student from the StudentsList
if (isDeleted) StudentsList.Remove(student);
// then, continue to save changes for the next student in queue
if (_actionQueue.BeginOneAction() == false)
{
// all changes are saved, we need to send notification
_proxy.DecrementCallCount();
if (SaveStudentChangesCompleted != null &&
_lastError == null && string.IsNullOrEmpty(warningMessage))
{
SaveStudentChangesCompleted(this,
new ResultArgs<string>(string.Empty, null, false, null));
}
}
}
else
{
// if there is a warning message, we need to stop and send notification
// on first occurrence, in other words, if _lastError is still null
_actionQueue.Clear();
_proxy.DecrementCallCount();
if (SaveStudentChangesCompleted != null &&
(_lastError == null || AllowMultipleErrors))
{
SaveStudentChangesCompleted(this,
new ResultArgs<string>(warningMessage, null, true, null));
}
}
}
catch (Exception ex)
{
// if there is an error, we need to stop and send notification
// on first occurrence, in other words, if _lastError is still null
_actionQueue.Clear();
_proxy.DecrementCallCount();
if (SaveStudentChangesCompleted != null &&
(_lastError == null || AllowMultipleErrors))
{
SaveStudentChangesCompleted(this,
new ResultArgs<string>(string.Empty, ex, true, null));
}
_lastError = ex;
}
});
}
/// <summary>
/// AsyncCallback for BeginUpdateInstructor
/// </summary>
/// <param name="result"></param>
private void BeginUpdateInstructorComplete(IAsyncResult result)
{
ThreadHelper.BeginInvokeOnUIThread(
delegate
{
try
{
// get the return values
var returnList = _proxy.EndUpdateInstructor(result);
// returnList[0] could be a warning message
var warningMessage = returnList[0] as string;
// returnList[1] is the updated instructor Id
var updatedInstructorId = Convert.ToInt32(returnList[1]);
// get the instructorId for the instructor that finished saving changes
var instructorId = Convert.ToInt32(result.AsyncState);
var instructor = InstructorsList.Single(n => n.PersonId == instructorId);
// update the instructor Id if the instructor State is Added
if (instructor.ChangeTracker.State == ObjectState.Added)
instructor.PersonId = updatedInstructorId;
if (string.IsNullOrEmpty(warningMessage))
{
var isDeleted = instructor.ChangeTracker.State == ObjectState.Deleted;
// if there is no error or warning message, call AcceptObjectGraphChanges() first
instructor.AcceptObjectGraphChanges();
// if State is Deleted, remove the instructor from the InstructorsList
if (isDeleted) InstructorsList.Remove(instructor);
// then, continue to save changes for the next instructor in queue
if (_actionQueue.BeginOneAction() == false)
{
// all changes are saved, we need to send notification
_proxy.DecrementCallCount();
if (SaveInstructorChangesCompleted != null &&
_lastError == null && string.IsNullOrEmpty(warningMessage))
{
SaveInstructorChangesCompleted(this,
new ResultArgs<string>(string.Empty, null, false, null));
}
}
}
else
{
// if there is a warning message, we need to stop and send notification
// on first occurrence, in other words, if _lastError is still null
_actionQueue.Clear();
_proxy.DecrementCallCount();
if (SaveInstructorChangesCompleted != null &&
(_lastError == null || AllowMultipleErrors))
{
SaveInstructorChangesCompleted(this,
new ResultArgs<string>(warningMessage, null, true, null));
}
}
}
catch (Exception ex)
{
// if there is an error, we need to stop and send notification
// on first occurrence, in other words, if _lastError is still null
_actionQueue.Clear();
_proxy.DecrementCallCount();
if (SaveInstructorChangesCompleted != null &&
(_lastError == null || AllowMultipleErrors))
{
SaveInstructorChangesCompleted(this,
new ResultArgs<string>(string.Empty, ex, true, null));
}
_lastError = ex;
}
});
}
/// <summary>
/// AsyncCallback for BeginUpdateCourse
/// </summary>
/// <param name="result"></param>
private void BeginUpdateCourseComplete(IAsyncResult result)
{
ThreadHelper.BeginInvokeOnUIThread(
delegate
{
try
{
// get the return values
var returnList = _proxy.EndUpdateCourse(result);
// returnList[0] could be a warning message
var warningMessage = returnList[0] as string;
// returnList[1] is the updated course Id
var updatedCourseId = Convert.ToInt32(returnList[1]);
// get the courseId for the course that finished saving changes
var courseId = Convert.ToInt32(result.AsyncState);
var course = CoursesList.Single(n => n.CourseId == courseId);
// update the course Id if the course State is Added
if (course.ChangeTracker.State == ObjectState.Added)
course.CourseId = updatedCourseId;
if (string.IsNullOrEmpty(warningMessage))
{
var isDeleted = course.ChangeTracker.State == ObjectState.Deleted;
// if there is no error or warning message, call AcceptObjectGraphChanges() first
course.AcceptObjectGraphChanges();
// if State is Deleted, remove the course from the CoursesList
if (isDeleted) CoursesList.Remove(course);
// then, continue to save changes for the next course in queue
if (_actionQueue.BeginOneAction() == false)
{
// all changes are saved, we need to send notification
_proxy.DecrementCallCount();
if (SaveCourseChangesCompleted != null &&
_lastError == null &&
string.IsNullOrEmpty(warningMessage))
{
SaveCourseChangesCompleted(this,
new ResultArgs<string>(
string.Empty, null,
false, null));
}
}
}
else
{
// if there is a warning message, we need to stop and send notification
// on first occurrence, in other words, if _lastError is still null
_actionQueue.Clear();
_proxy.DecrementCallCount();
if (SaveCourseChangesCompleted != null &&
(_lastError == null || AllowMultipleErrors))
{
SaveCourseChangesCompleted(this,
new ResultArgs<string>(
warningMessage, null,
true, null));
}
}
}
catch (Exception ex)
{
// if there is an error, we need to stop and send notification
// on first occurrence, in other words, if _lastError is still null
_actionQueue.Clear();
_proxy.DecrementCallCount();
if (SaveCourseChangesCompleted != null &&
(_lastError == null || AllowMultipleErrors))
{
SaveCourseChangesCompleted(this,
new ResultArgs<string>(
string.Empty, ex, true,
null));
}
_lastError = ex;
}
});
}
#endregion "Private Methods"
}
}