/// <summary> /// Add a new task to the Tasks collection and the ListBox /// </summary> /// <param name="tl">TaskList to add to</param> /// <param name="task">Task to add</param> public void AddTask(TaskList tl, Task task) { // add the task tl.Tasks.Add(task); tl.Tasks = OrderTasks(tl.Tasks); // get the correct index based on the current sort int newIndex = tl.Tasks.IndexOf(task); // reinsert it at the correct place ListBox.Items.Insert(newIndex, RenderTask(task)); }
/// <summary> /// Resolve Task conflicts between a local and remote TaskList /// </summary> /// <param name="localTaskList">Local task listType</param> /// <param name="remoteTaskList">Task listType retrieved from the data service</param> private static void ResolveTasks(TaskList localTaskList, TaskList remoteTaskList) { foreach (Task localTask in localTaskList.Tasks) { bool foundTask = false; foreach (Task remoteTask in remoteTaskList.Tasks) { if (localTask.ID == remoteTask.ID) { foundTask = true; break; } } if (foundTask == false) { remoteTaskList.Tasks.Add(localTask); } } }
// When page is navigated to set data context to selected item in listType protected override void OnNavigatedTo(NavigationEventArgs e) { // trace event TraceHelper.AddMessage("Task: OnNavigatedTo"); // check to make sure we haven't initialized yet if (isInitialized == true) return; // create the keyboard helper for tabbed navigation this.keyboardHelper = new KeyboardHelper(LayoutRoot); // reset the tab index tabIndex = 0; // don't render the tasklist field by default bool renderTaskListField = false; // find the taskist that this task would belong to string taskListIDString = ""; if (NavigationContext.QueryString.TryGetValue("taskListID", out taskListIDString)) { Guid taskListID = new Guid(taskListIDString); if (taskListID != Guid.Empty) { try { //taskList = App.ViewModel.TaskLists.Single(tl => tl.ID == taskListID); taskList = App.ViewModel.LoadList(taskListID); } catch (Exception) { taskList = null; } } } // if we haven't found a tasklist, use the default one if (taskList == null) { taskList = App.ViewModel.DefaultTaskList; renderTaskListField = true; } string taskIDString = ""; // must have a task ID passed (either a valid GUID or "new") if (NavigationContext.QueryString.TryGetValue("ID", out taskIDString) == false) { // trace page navigation TraceHelper.StartMessage("Task: Navigate back"); NavigationService.GoBack(); return; } // the task page is used to construct a new item if (taskIDString == "new") { // remove the "actions" tab //TaskPagePivotControl.Items.RemoveAt(0); //((PivotItem)(TaskPagePivotControl.Items[0])).IsEnabled = false; taskCopy = new Task() { TaskListID = taskList.ID }; thisTask = null; RenderViewTask(taskCopy); RenderEditTask(taskCopy, renderTaskListField); // navigate the pivot control to the "edit" view TaskPagePivotControl.SelectedIndex = 1; } else { // editing an existing item Guid id = new Guid(taskIDString); //thisTask = App.ViewModel.Tasks.Single(t => t.ID == id); //taskList = App.ViewModel.TaskLists.Single(tl => tl.ID == thisTask.TaskListID); thisTask = taskList.Tasks.Single(t => t.ID == id); // make a deep copy of the task for local binding taskCopy = new Task(thisTask); DataContext = taskCopy; RenderViewTask(taskCopy); RenderEditTask(taskCopy, false); } // set the initialized flag isInitialized = true; }
/// <summary> /// Find a task by ID and then return its index /// </summary> /// <param name="observableCollection"></param> /// <param name="taskList"></param> /// <returns></returns> private int IndexOf(TaskList tasklist, Task task) { try { Task taskRef = tasklist.Tasks.Single(t => t.ID == task.ID); return tasklist.Tasks.IndexOf(taskRef); } catch (Exception) { return -1; } }
public TaskList(TaskList list) { Copy(list); }
public TaskList(TaskList list) { Copy(list, true); }
private void SetContext(TaskList newTaskList) { // dispatch all this work on the UI thread in order to stop the app from blocking //Deployment.Current.Dispatcher.BeginInvoke(() => //{ // if a new copy wasn't passed, create a new one now (to facilitate databinding) if (newTaskList == null) newTaskList = new TaskList(taskList); // find the current tasklist's index and replace the entry in the viewmodel's TaskLists collection // this call will return -1 if the tasklist's index is not found, because we are filtering by tag or doing a search // in that case, we don't need to replace the list int index = IndexOf(App.ViewModel.TaskLists, taskList); if (index >= 0) { // replace the existing list with the new reference App.ViewModel.TaskLists[index] = newTaskList; } // replace the top-level reference taskList = newTaskList; // reset the contexts for databinding DataContext = newTaskList; OrderedSource[0].Source = null; OrderedSource[1].Source = null; OrderedSource[2].Source = null; // set the source for the current tab (doing all three is too expensive) OrderedSource[PivotControl.SelectedIndex].Source = taskList.Tasks; //}); }
/// <summary> /// Find a tasklist by ID and then return its index /// </summary> /// <param name="observableCollection"></param> /// <param name="taskList"></param> /// <returns></returns> private int IndexOf(ObservableCollection<TaskList> lists, TaskList taskList) { try { TaskList taskListRef = lists.Single(tl => tl.ID == taskList.ID); return lists.IndexOf(taskListRef); } catch (Exception) { return -1; } }
private void DeleteCompletedMenuItem_Click(object sender, EventArgs e) { MessageBoxResult result = MessageBox.Show("delete all completed tasks in this list?", "confirm delete", MessageBoxButton.OKCancel); if (result != MessageBoxResult.OK) return; // we will be building a new tasklist of only the non-completed items TaskList newTaskList = new TaskList(taskList); newTaskList.Tasks.Clear(); foreach (var task in taskList.Tasks) { if (task.Complete == true) { // enqueue the Web Request Record RequestQueue.EnqueueRequestRecord( new RequestQueue.RequestRecord() { ReqType = RequestQueue.RequestRecord.RequestType.Delete, Body = task }); } else { // add the non-completed task to the new list newTaskList.Tasks.Add(task); } } // replace the main tasklist and databind to the new list SetContext(newTaskList); // save the changes to local storage StorageHelper.WriteTaskLists(App.ViewModel.TaskLists); // trigger a databinding refresh for tasks App.ViewModel.NotifyPropertyChanged("Tasks"); // trigger a sync with the Service App.ViewModel.SyncWithService(); }
/// <summary> /// Remove a task in the list and the ListBox /// </summary> /// <param name="tl">TaskList that the task belongs to</param> /// <param name="task">Task to remove</param> public void RemoveTask(TaskList tl, Task task) { // get the current index based on the current sort int currentIndex = tl.Tasks.IndexOf(task); // remove the task from the tasklist tl.Tasks.Remove(task); // remove the task's ListBoxItem from the current place ListBox.Items.RemoveAt(currentIndex); }
public TaskListHelper(TaskList taskList, RoutedEventHandler checkBoxClickEvent, RoutedEventHandler tagClickEvent) { this.taskList = taskList; this.checkBoxClickEvent = checkBoxClickEvent; this.tagClickEvent = tagClickEvent; }
/// <summary> /// ReOrder a task in the list and the ListBox /// </summary> /// <param name="tl">TaskList that the task belongs to</param> /// <param name="task">Task to reorder</param> public void ReOrderTask(TaskList tl, Task task) { // get the current index based on the current sort int currentIndex = tl.Tasks.IndexOf(task); // order the list by the correct fields tl.Tasks = OrderTasks(tl.Tasks); // get the correct index based on the current sort int newIndex = tl.Tasks.IndexOf(task); // remove the task's ListBoxItem from the current place ListBox.Items.RemoveAt(currentIndex); // reinsert it at the correct place ListBox.Items.Insert(newIndex, RenderTask(task)); }
/// <summary> /// Render a list (in lieu of databinding) /// </summary> /// <param name="tl">TaskList to render</param> public void RenderList(TaskList tl) { // if the tasklist is null, nothing to do if (tl == null) return; // trace the event TraceHelper.AddMessage("List: RenderList"); // order by correct fields tl.Tasks = OrderTasks(tl.Tasks); /* // create the top-level grid FrameworkElement element; Grid grid = new Grid(); grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(40d) }); grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); grid.Children.Add(element = new TextBlock() { Text = tl.Name, Margin = new Thickness(10, -28, 0, 10), Style = (Style)App.Current.Resources["PhoneTextAccentStyle"], FontSize = (double)App.Current.Resources["PhoneFontSizeExtraLarge"], FontFamily = (FontFamily)App.Current.Resources["PhoneFontFamilySemiLight"] }); element.SetValue(Grid.RowProperty, 0); ListBox lb = new ListBox() { Margin = new Thickness(0, 0, 0, 0) }; lb.SetValue(Grid.RowProperty, 1); lb.SelectionChanged += new SelectionChangedEventHandler(ListBox_SelectionChanged); grid.Children.Add(lb); */ // clear the listbox ListBox.Items.Clear(); // if the number of tasks is smaller than 10, render them all immediately if (tl.Tasks.Count <= rendersize) { // render the tasks foreach (Task t in tl.Tasks) ListBox.Items.Add(RenderTask(t)); } else { // render the first 10 tasks immediately foreach (Task t in tl.Tasks.Take(rendersize)) ListBox.Items.Add(RenderTask(t)); // schedule the rendering of the rest of the tasks on the UI thread Deployment.Current.Dispatcher.BeginInvoke(() => { foreach (Task t in tl.Tasks.Skip(rendersize)) ListBox.Items.Add(RenderTask(t)); }); } // set the content for the pivot item (which will trigger the rendering) //((PivotItem)PivotControl.SelectedItem).Content = grid; // trace the event TraceHelper.AddMessage("Finished List RenderList"); }
/// <summary> /// Initialize default tasklists /// </summary> /// <returns></returns> private ObservableCollection<TaskList> InitializeTaskLists() { ObservableCollection<TaskList> taskLists = new ObservableCollection<TaskList>(); TaskList taskList; Task task; // create a To Do list taskLists.Add(taskList = new TaskList() { Name = "To Do", ListTypeID = ListType.ToDo, Tasks = new ObservableCollection<Task>() }); // add to the dictionary Lists.Add(taskList.ID, taskList); // enqueue the Web Request Record RequestQueue.EnqueueRequestRecord( new RequestQueue.RequestRecord() { ReqType = RequestQueue.RequestRecord.RequestType.Insert, Body = taskList, ID = taskList.ID }); // create the Welcome task taskList.Tasks.Add(task = new Task() { Name = "Welcome to TaskStore!", Description="Tap the browse button below to discover more about the TaskStore application.", TaskListID = taskList.ID, Due = DateTime.Today.Date, PriorityID = 0, Website = WebServiceHelper.BaseUrl + "/Home/WelcomeWP7" /*"/Content/Welcome.html"*/ }); // enqueue the Web Request Record RequestQueue.EnqueueRequestRecord( new RequestQueue.RequestRecord() { ReqType = RequestQueue.RequestRecord.RequestType.Insert, Body = task, ID = task.ID }); // create a shopping list taskLists.Add(taskList = new TaskList() { Name = "Shopping", ListTypeID = ListType.Shopping, Tasks = new ObservableCollection<Task>() }); // add to the dictionary Lists.Add(taskList.ID, taskList); // enqueue the Web Request Record RequestQueue.EnqueueRequestRecord( new RequestQueue.RequestRecord() { ReqType = RequestQueue.RequestRecord.RequestType.Insert, Body = taskList, ID = taskList.ID }); return taskLists; }
public TaskList(TaskList list, bool deepCopy) { Copy(list, deepCopy); }
private void MainPage_Loaded(object sender, RoutedEventArgs e) { TraceHelper.AddMessage("Main: Loaded"); // if data isn't loaded from storage yet, load the app data if (!App.ViewModel.IsDataLoaded) { // Load app data from local storage (user creds, about tab data, constants, list types, tasklists, etc) App.ViewModel.LoadData(); } // if haven't synced with web service yet, try now if (initialSync == false) { // attempt to sync with the Service App.ViewModel.SyncWithService(); initialSync = true; } taskList = new TaskList() { Tasks = FilterTasks(App.ViewModel.Tasks) }; // create the TaskListHelper TaskListHelper = new TaskStoreWinPhone.TaskListHelper( taskList, new RoutedEventHandler(Tasks_CompleteCheckbox_Click), new RoutedEventHandler(Tag_HyperlinkButton_Click)); // store the current listbox and ordering TaskListHelper.ListBox = TasksListBox; TaskListHelper.OrderBy = "due"; // render the tasks TaskListHelper.RenderList(taskList); // add a property changed handler for the Tasks property if (!addedTasksPropertyChangedHandler) { App.ViewModel.PropertyChanged += new PropertyChangedEventHandler((s, args) => { // if the Tasks property was signaled, re-filter and re-render the tasks list if (args.PropertyName == "Tasks") { taskList.Tasks = FilterTasks(App.ViewModel.Tasks); TaskListHelper.RenderList(taskList); } }); addedTasksPropertyChangedHandler = true; } // set the datacontext SearchHeader.DataContext = this; // trace exit TraceHelper.AddMessage("Exiting Main Loaded"); }
// When page is navigated to set data context to selected item in listType protected override void OnNavigatedTo(NavigationEventArgs e) { // trace data TraceHelper.AddMessage("TaskList: OnNavigatedTo"); string IDString = ""; string typeString = ""; Guid id; if (NavigationContext.QueryString.TryGetValue("type", out typeString) == false) { // trace page navigation TraceHelper.StartMessage("TaskList: Navigate back"); // navigate back NavigationService.GoBack(); return; } switch (typeString) { case "TaskList": if (NavigationContext.QueryString.TryGetValue("ID", out IDString) == false) { // trace page navigation TraceHelper.StartMessage("TaskList: Navigate back"); // navigate back NavigationService.GoBack(); return; } id = new Guid(IDString); // get the tasklist and make it the datacontext try { taskList = App.ViewModel.TaskLists.Single(tl => tl.ID == id); SetContext(taskList); } catch (Exception ex) { // the list isn't found - this can happen when the list we were just // editing was removed in TaskListEditor, which then goes back to TaskListPage. // this will send us back to the MainPage which is appropriate. // trace page navigation TraceHelper.StartMessage(String.Format("TaskList: Navigate back (exception: {0})", ex.Message)); // navigate back NavigationService.GoBack(); return; } break; case "Tag": if (NavigationContext.QueryString.TryGetValue("ID", out IDString) == false) { // trace page navigation TraceHelper.StartMessage("TaskList: Navigate back"); // navigate back NavigationService.GoBack(); return; } id = new Guid(IDString); // create a filter try { tag = App.ViewModel.Tags.Single(t => t.ID == id); taskList = new TaskList() { ID = Guid.Empty, Name = String.Format("tasks with {0} tag", tag.Name), Tasks = App.ViewModel.Tasks }; SetContext(taskList); foreach (var source in OrderedSource) source.Filter += new FilterEventHandler(Tag_Filter); } catch (Exception) { // the tag isn't found - this can happen when the tag we were just // editing was removed in TagListEditor, which then goes back to TaskListPage. // this will send us back to the MainPage which is appropriate. // trace page navigation TraceHelper.StartMessage("TaskList: Navigate back"); // navigate back NavigationService.GoBack(); return; } break; default: // trace page navigation TraceHelper.StartMessage("TaskList: Navigate back"); // navigate back NavigationService.GoBack(); return; } // workaround for the CollectionViewSource wrappers that are used for the different ListBox sorts // setting SelectionMode to Multiple removes the issue where the SelectionChanged event handler gets // invoked every time the list is changed (which triggers a re-sort). The SelectionMode gets reset back // to Single when the SelectionChanged events handler gets called (for a valid reason - i.e. user action) SetSelectionMode(SelectionMode.Multiple); // enable the listbox disableListBoxSelectionChanged = false; // trace data TraceHelper.AddMessage("Exiting TaskList OnNavigatedTo"); }
// When page is navigated to set data context to selected item in listType protected override void OnNavigatedTo(NavigationEventArgs e) { // trace data TraceHelper.AddMessage("List: OnNavigatedTo"); string IDString = ""; string typeString = ""; Guid id; if (NavigationContext.QueryString.TryGetValue("type", out typeString) == false) { // trace page navigation TraceHelper.StartMessage("List: Navigate back"); // navigate back NavigationService.GoBack(); return; } switch (typeString) { case "TaskList": if (NavigationContext.QueryString.TryGetValue("ID", out IDString) == false) { // trace page navigation TraceHelper.StartMessage("List: Navigate back"); // navigate back NavigationService.GoBack(); return; } id = new Guid(IDString); // get the tasklist and make it the datacontext try { taskList = App.ViewModel.LoadList(id); // if the load failed, this list has been deleted if (taskList == null) { // the list isn't found - this can happen when the list we were just // editing was removed in TaskListEditor, which then goes back to TaskListPage. // this will send us back to the MainPage which is appropriate. // trace page navigation TraceHelper.StartMessage("List: Navigate back"); // navigate back NavigationService.GoBack(); return; } } catch (Exception ex) { // the list isn't found - this can happen when the list we were just // editing was removed in TaskListEditor, which then goes back to TaskListPage. // this will send us back to the MainPage which is appropriate. // trace page navigation TraceHelper.StartMessage(String.Format("List: Navigate back (exception: {0})", ex.Message)); // navigate back NavigationService.GoBack(); return; } break; case "Tag": if (NavigationContext.QueryString.TryGetValue("ID", out IDString) == false) { // trace page navigation TraceHelper.StartMessage("List: Navigate back"); // navigate back NavigationService.GoBack(); return; } id = new Guid(IDString); // create a filter try { tag = App.ViewModel.Tags.Single(t => t.ID == id); taskList = new TaskList() { ID = Guid.Empty, Name = String.Format("tasks with {0} tag", tag.Name), Tasks = App.ViewModel.Tasks.Where(t => t.TaskTags.Any(tg => tg.TagID == tag.ID)).ToObservableCollection() }; } catch (Exception) { // the tag isn't found - this can happen when the tag we were just // editing was removed in TagListEditor, which then goes back to TaskListPage. // this will send us back to the MainPage which is appropriate. // trace page navigation TraceHelper.StartMessage("List: Navigate back"); // navigate back NavigationService.GoBack(); return; } break; default: // trace page navigation TraceHelper.StartMessage("List: Navigate back"); // navigate back NavigationService.GoBack(); return; } // set datacontext DataContext = taskList; // create the TaskListHelper TaskListHelper = new TaskStoreWinPhone.TaskListHelper( taskList, new RoutedEventHandler(CompleteCheckbox_Click), new RoutedEventHandler(Tag_HyperlinkButton_Click)); // store the current listbox and ordering PivotItem item = (PivotItem) PivotControl.Items[PivotControl.SelectedIndex]; TaskListHelper.ListBox = (ListBox)((Grid)item.Content).Children[1]; TaskListHelper.OrderBy = (string)item.Header; // trace data TraceHelper.AddMessage("Exiting List OnNavigatedTo"); }
private void ImportTemplatePopup_ImportButton_Click(object sender, RoutedEventArgs e) { TaskList tl = ImportTemplatePopupTaskListPicker.SelectedItem as TaskList; if (tl == null) return; // add the task to a new tasklist reference (to trigger databinding) var newTaskList = new TaskList(taskList); foreach (Task t in tl.Tasks) { DateTime now = DateTime.UtcNow; // create the new task Task task = new Task(t) { ID = Guid.NewGuid(), TaskListID = taskList.ID, Created = now, LastModified = now }; // recreate the tasktags (they must be unique) if (task.TaskTags != null && task.TaskTags.Count > 0) { foreach (var tt in task.TaskTags) { tt.ID = Guid.NewGuid(); } } // enqueue the Web Request Record RequestQueue.EnqueueRequestRecord( new RequestQueue.RequestRecord() { ReqType = RequestQueue.RequestRecord.RequestType.Insert, Body = task }); // add the task to the local collection newTaskList.Tasks.Add(task); } // replace the main tasklist and databind to the new list SetContext(newTaskList); // save the changes to local storage StorageHelper.WriteTaskLists(App.ViewModel.TaskLists); // trigger a databinding refresh for tasks App.ViewModel.NotifyPropertyChanged("Tasks"); // trigger a sync with the Service App.ViewModel.SyncWithService(); // close the popup ImportTemplatePopup.IsOpen = false; }
private void DeleteCompletedMenuItem_Click(object sender, EventArgs e) { MessageBoxResult result = MessageBox.Show("delete all completed tasks in this list?", "confirm delete", MessageBoxButton.OKCancel); if (result != MessageBoxResult.OK) return; // create a copy of the tasklist to foreach over. this is because we can't delete // from the original collection while it's being enumerated. the copy we make is shallow // so as not to create brand new Task objects, but then we add all the task references to // an new Tasks collection that won't interfere with the existing one. TaskList tl = new TaskList(taskList, false); tl.Tasks = new ObservableCollection<Task>(); foreach (Task t in taskList.Tasks) tl.Tasks.Add(t); // remove any completed tasks from the original tasklist foreach (var task in tl.Tasks) { if (task.Complete == true) { // enqueue the Web Request Record RequestQueue.EnqueueRequestRecord( new RequestQueue.RequestRecord() { ReqType = RequestQueue.RequestRecord.RequestType.Delete, Body = task }); // remove the task from the original collection and from ListBox TaskListHelper.RemoveTask(taskList, task); } } // save the changes to local storage StorageHelper.WriteList(taskList); // trigger a sync with the Service App.ViewModel.SyncWithService(); }
private void QuickAddPopup_AddButton_Click(object sender, RoutedEventArgs e) { string name = PopupTextBox.Text; // don't add empty items if (name == null || name == "") return; // create the new task Task task = new Task() { Name = name, TaskListID = taskList.ID, LastModified = DateTime.UtcNow }; // enqueue the Web Request Record RequestQueue.EnqueueRequestRecord( new RequestQueue.RequestRecord() { ReqType = RequestQueue.RequestRecord.RequestType.Insert, Body = task }); // add the task to a new tasklist reference (to trigger databinding) var newTaskList = new TaskList(taskList); newTaskList.Tasks.Add(task); // replace the main tasklist and databind to the new list SetContext(newTaskList); // save the changes to local storage StorageHelper.WriteTaskLists(App.ViewModel.TaskLists); // trigger a databinding refresh for tasks App.ViewModel.NotifyPropertyChanged("Tasks"); // trigger a sync with the Service App.ViewModel.SyncWithService(); // clear the textbox and focus back to it PopupTextBox.Text = ""; PopupTextBox.Focus(); }
public void Copy(TaskList obj) { // copy all of the properties foreach (PropertyInfo pi in this.GetType().GetProperties()) { if (pi.CanWrite) { var val = pi.GetValue(obj, null); pi.SetValue(this, val, null); } } // reinitialize the Tasks collection this.tasks = new ObservableCollection<Task>(); foreach (Task t in obj.tasks) { this.tasks.Add(new Task(t)); } }
void TaskListEditor_Loaded(object sender, RoutedEventArgs e) { // trace event TraceHelper.AddMessage("ListEditor: Loaded"); string taskListIDString = ""; if (NavigationContext.QueryString.TryGetValue("ID", out taskListIDString)) { if (taskListIDString == "new") { // new tasklist taskListCopy = new TaskList(); DataContext = taskListCopy; } else { Guid taskListID = new Guid(taskListIDString); taskList = App.ViewModel.TaskLists.Single<TaskList>(tl => tl.ID == taskListID); // make a deep copy of the task for local binding taskListCopy = new TaskList(taskList); DataContext = taskListCopy; // add the delete button to the ApplicationBar var button = new ApplicationBarIconButton() { Text = "Delete", IconUri = new Uri("/Images/appbar.delete.rest.png", UriKind.Relative) }; button.Click += new EventHandler(DeleteButton_Click); // insert after the save button but before the cancel button ApplicationBar.Buttons.Add(button); } RenderListTypes(); } }
public void Copy(TaskList obj, bool deepCopy) { if (obj == null) return; // copy all of the properties foreach (PropertyInfo pi in this.GetType().GetProperties()) { if (pi.CanWrite) { var val = pi.GetValue(obj, null); pi.SetValue(this, val, null); } } if (deepCopy) { // reinitialize the Tasks collection this.tasks = new ObservableCollection<Task>(); foreach (Task t in obj.tasks) { this.tasks.Add(new Task(t)); } } else { this.tasks = new ObservableCollection<Task>(); } NotifyPropertyChanged("Tasks"); }