private void RenderViewTask(Task task) { int row = 0; // render fields foreach (TaskStoreClientEntities.Action action in App.ViewModel.Constants.Actions.OrderBy(a => a.SortOrder)) { PropertyInfo pi; // make sure the property exists on the local type try { pi = task.GetType().GetProperty(action.FieldName); if (pi == null) continue; // see comment below } catch (Exception) { // we can't do anything with this property since we don't have it on the local type // this indicates that the phone software isn't caught up with the service version // but that's ok - we can keep going continue; } // get the value of the property var val = pi.GetValue(task, null); // for our purposes, an empty value is the same as null if (val != null && val.GetType() == typeof(String)) if ((string)val == "") val = null; // render this property if it's not null/empty if (val != null) { // first make sure that we do want to render (type-specific logic goes here) switch (action.ActionType) { case "Postpone": // if the date is already further in the future than today, omit adding this action if (((DateTime)val).Date > DateTime.Today.Date) continue; break; } // add a new row ViewGrid.RowDefinitions.Add(new RowDefinition() { MaxHeight = 72 }); string valueString = val.ToString(); Thickness margin = new Thickness(12, 20, 0, 0); // bounding rectangle of padding // create a new buton for the action (verb) var button = new Button() { Content = action.DisplayName, MinWidth = 200 }; button.SetValue(Grid.ColumnProperty, 0); button.SetValue(Grid.RowProperty, row); ViewGrid.Children.Add(button); // create a label which holds the noun the verb will act upon // usually extracted from the task field's contents var valueTextBlock = new TextBlock() { DataContext = task, Style = (Style)App.Current.Resources["PhoneTextNormalStyle"], Margin = margin, }; //value.SetBinding(TextBlock.TextProperty, new Binding(pi.Name)); valueTextBlock.SetValue(Grid.ColumnProperty, 1); valueTextBlock.SetValue(Grid.RowProperty, row++); ViewGrid.Children.Add(valueTextBlock); // render the action based on the action type switch (action.ActionType) { case "Navigate": try { TaskList tl = App.ViewModel.TaskLists.Single(t => t.ID == (Guid)val); valueTextBlock.Text = String.Format("to {0}", tl.Name); button.Click += new RoutedEventHandler(delegate { // trace page navigation TraceHelper.StartMessage("Task: Navigate to TaskList"); // Navigate to the new page //NavigationService.Navigate(new Uri("/TaskListPage.xaml?type=TaskList&ID=" + tl.ID.ToString(), UriKind.Relative)); NavigationService.Navigate(new Uri("/ListPage.xaml?type=TaskList&ID=" + tl.ID.ToString(), UriKind.Relative)); }); } catch (Exception) { valueTextBlock.Text = "(list not found)"; } break; case "Postpone": valueTextBlock.Text = "to tomorrow"; button.Click += new RoutedEventHandler(delegate { pi.SetValue(task, DateTime.Today.Date.AddDays(1.0), null); taskList.NotifyPropertyChanged("FirstDue"); taskList.NotifyPropertyChanged("FirstDueColor"); }); break; case "AddToCalendar": valueTextBlock.SetBinding(TextBlock.TextProperty, new Binding("DueDisplay")); button.Click += new RoutedEventHandler(delegate { taskList.NotifyPropertyChanged("FirstDue"); taskList.NotifyPropertyChanged("FirstDueColor"); }); break; case "Map": valueTextBlock.SetBinding(TextBlock.TextProperty, new Binding(pi.Name)); button.Click += new RoutedEventHandler(delegate { #if WINPHONE7 // Pre-MANGO string mapUrl = "maps:"; bool space = false; foreach (string part in valueString.Split(' ')) { if (space == true) mapUrl += "%20"; mapUrl += part; space = true; } WebBrowserTask mapTask = new WebBrowserTask() { Uri = new Uri(mapUrl) }; #else // MANGO BingMapsTask mapTask = new BingMapsTask() { SearchTerm = valueString }; #endif mapTask.Show(); }); break; case "Phone": // format as phone number valueTextBlock.SetBinding(TextBlock.TextProperty, new Binding(pi.Name)); button.Click += new RoutedEventHandler(delegate { PhoneCallTask phoneCallTask = new PhoneCallTask() { PhoneNumber = (string)val }; phoneCallTask.Show(); }); break; case "TextMessage": valueTextBlock.SetBinding(TextBlock.TextProperty, new Binding(pi.Name)); button.Click += new RoutedEventHandler(delegate { SmsComposeTask smsTask = new SmsComposeTask() { To = (string)val }; smsTask.Show(); }); break; case "Browse": valueTextBlock.SetBinding(TextBlock.TextProperty, new Binding(pi.Name)); button.Click += new RoutedEventHandler(delegate { string url = (string)val; if (url.Substring(1, 4) != "http") url = String.Format("http://{0}", url); WebBrowserTask browserTask = new WebBrowserTask() { Uri = new Uri(url) }; browserTask.Show(); }); break; case "Email": valueTextBlock.SetBinding(TextBlock.TextProperty, new Binding(pi.Name)); button.Click += new RoutedEventHandler(delegate { EmailComposeTask emailTask = new EmailComposeTask() { To = (string)val }; emailTask.Show(); }); break; } } } }
private void RenderEditTaskField(Task task, FieldType fieldType) { PropertyInfo pi; // make sure the property exists on the local type try { pi = task.GetType().GetProperty(fieldType.Name); if (pi == null) return; // see comment below } catch (Exception) { // we can't do anything with this property since we don't have it on the local type // this indicates that the phone software isn't caught up with the service version return; } // get the value of the property var val = pi.GetValue(task, null); ListBoxItem listBoxItem = new ListBoxItem(); StackPanel EditStackPanel = new StackPanel(); listBoxItem.Content = EditStackPanel; EditStackPanel.Children.Add( new TextBlock() { Text = fieldType.DisplayName, Style = (Style)App.Current.Resources["PhoneTextNormalStyle"] }); // create a textbox (will be used by the majority of field types) double minWidth = App.Current.RootVisual.RenderSize.Width; if ((int)minWidth == 0) minWidth = ((this.Orientation & PageOrientation.Portrait) == PageOrientation.Portrait) ? 480.0 : 800.0; TextBox tb = new TextBox() { DataContext = taskCopy, MinWidth = minWidth, IsTabStop = true }; tb.SetBinding(TextBox.TextProperty, new Binding(pi.Name) { Mode = BindingMode.TwoWay }); bool notMatched = false; // render the right control based on the type switch (fieldType.DisplayType) { case "String": tb.InputScope = new InputScope() { Names = { new InputScopeName() { NameValue = InputScopeNameValue.Text } } }; tb.LostFocus += new RoutedEventHandler(delegate { pi.SetValue(taskCopy, tb.Text, null); }); tb.TabIndex = tabIndex++; tb.KeyUp += new KeyEventHandler(TextBox_KeyUp); EditStackPanel.Children.Add(tb); break; case "TextBox": tb.InputScope = new InputScope() { Names = { new InputScopeName() { NameValue = InputScopeNameValue.Text } } }; tb.AcceptsReturn = true; tb.TextWrapping = TextWrapping.Wrap; tb.Height = 300; tb.TabIndex = tabIndex++; tb.LostFocus += new RoutedEventHandler(delegate { pi.SetValue(taskCopy, tb.Text, null); }); EditStackPanel.Children.Add(tb); break; case "Phone": case "PhoneNumber": tb.InputScope = new InputScope() { Names = { new InputScopeName() { NameValue = InputScopeNameValue.TelephoneNumber } } }; tb.LostFocus += new RoutedEventHandler(delegate { pi.SetValue(taskCopy, tb.Text, null); }); tb.TabIndex = tabIndex++; StackPanel innerPanel = RenderEditTaskImageButtonPanel(tb); ImageButton imageButton = (ImageButton)innerPanel.Children[1]; imageButton.Click += new RoutedEventHandler(delegate { PhoneNumberChooserTask chooser = new PhoneNumberChooserTask(); chooser.Completed += new EventHandler<PhoneNumberResult>((sender, e) => { if (e.TaskResult == TaskResult.OK && e.PhoneNumber != null && e.PhoneNumber != "") pi.SetValue(task, e.PhoneNumber, null); }); chooser.Show(); }); EditStackPanel.Children.Add(innerPanel); break; case "Website": tb.InputScope = new InputScope() { Names = { new InputScopeName() { NameValue = InputScopeNameValue.Url } } }; tb.LostFocus += new RoutedEventHandler(delegate { pi.SetValue(taskCopy, tb.Text, null); }); tb.TabIndex = tabIndex++; tb.KeyUp += new KeyEventHandler(TextBox_KeyUp); EditStackPanel.Children.Add(tb); break; case "Email": tb.InputScope = new InputScope() { Names = { new InputScopeName() { NameValue = InputScopeNameValue.EmailSmtpAddress } } }; tb.LostFocus += new RoutedEventHandler(delegate { pi.SetValue(taskCopy, tb.Text, null); }); tb.TabIndex = tabIndex++; tb.KeyUp += new KeyEventHandler(TextBox_KeyUp); innerPanel = RenderEditTaskImageButtonPanel(tb); imageButton = (ImageButton)innerPanel.Children[1]; imageButton.Click += new RoutedEventHandler(delegate { EmailAddressChooserTask chooser = new EmailAddressChooserTask(); chooser.Completed += new EventHandler<EmailResult>((sender, e) => { if (e.TaskResult == TaskResult.OK && e.Email != null && e.Email != "") pi.SetValue(task, e.Email, null); }); chooser.Show(); }); EditStackPanel.Children.Add(innerPanel); break; case "Location": case "Address": tb.InputScope = new InputScope() { Names = { new InputScopeName() { NameValue = InputScopeNameValue.AddressStreet }, new InputScopeName() { NameValue = InputScopeNameValue.AddressCity }, new InputScopeName() { NameValue = InputScopeNameValue.AddressStateOrProvince }, new InputScopeName() { NameValue = InputScopeNameValue.AddressCountryName }, } }; tb.LostFocus += new RoutedEventHandler(delegate { pi.SetValue(taskCopy, tb.Text, null); }); tb.TabIndex = tabIndex++; tb.KeyUp += new KeyEventHandler(TextBox_KeyUp); innerPanel = RenderEditTaskImageButtonPanel(tb); imageButton = (ImageButton)innerPanel.Children[1]; imageButton.Click += new RoutedEventHandler(delegate { // start the location service GeoCoordinateWatcher watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High); watcher.MovementThreshold = 20; // Use MovementThreshold to ignore noise in the signal. watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>((sender, e) => { if (e.Status == GeoPositionStatus.Ready) { // Use the Position property of the GeoCoordinateWatcher object to get the current location. GeoCoordinate co = watcher.Position.Location; tb.Text = co.Latitude.ToString("0.000") + "," + co.Longitude.ToString("0.000"); //Stop the Location Service to conserve battery power. watcher.Stop(); } }); watcher.Start(); }); EditStackPanel.Children.Add(innerPanel); break; case "Priority": ListPicker lp = new ListPicker() { MinWidth = minWidth, FullModeItemTemplate = (DataTemplate) App.Current.Resources["FullListPickerTemplate"], IsTabStop = true }; lp.ItemsSource = App.ViewModel.Constants.Priorities; lp.DisplayMemberPath = "Name"; int? lpval = (int?)pi.GetValue(taskCopy, null); if (lpval != null) lp.SelectedIndex = (int)lpval; else lp.SelectedIndex = 1; // HACK: hardcode to "Normal" priority. this should come from a table. lp.SelectionChanged += new SelectionChangedEventHandler(delegate { pi.SetValue(taskCopy, lp.SelectedIndex == 1 ? (int?)null : lp.SelectedIndex, null); }); lp.TabIndex = tabIndex++; EditStackPanel.Children.Add(lp); break; case "TaskList": ListPicker taskListPicker = new ListPicker() { MinWidth = minWidth, IsTabStop = true }; taskListPicker.ItemsSource = App.ViewModel.TaskLists; taskListPicker.DisplayMemberPath = "Name"; TaskList tl = App.ViewModel.TaskLists.FirstOrDefault(list => list.ID == taskList.ID); taskListPicker.SelectedIndex = App.ViewModel.TaskLists.IndexOf(tl); taskListPicker.SelectionChanged += new SelectionChangedEventHandler(delegate { pi.SetValue(taskCopy, App.ViewModel.TaskLists[taskListPicker.SelectedIndex].ID, null); }); taskListPicker.TabIndex = tabIndex++; EditStackPanel.Children.Add(taskListPicker); break; case "Integer": tb.InputScope = new InputScope() { Names = { new InputScopeName() { NameValue = InputScopeNameValue.Digits } } }; tb.LostFocus += new RoutedEventHandler(delegate { pi.SetValue(taskCopy, Convert.ToInt32(tb.Text), null); }); tb.TabIndex = tabIndex++; tb.KeyUp += new KeyEventHandler(TextBox_KeyUp); EditStackPanel.Children.Add(tb); break; case "Date": DatePicker dp = new DatePicker() { DataContext = taskCopy, MinWidth = minWidth, IsTabStop = true }; dp.SetBinding(DatePicker.ValueProperty, new Binding(pi.Name) { Mode = BindingMode.TwoWay }); dp.ValueChanged += new EventHandler<DateTimeValueChangedEventArgs>(delegate { pi.SetValue(taskCopy, dp.Value, null); taskList.NotifyPropertyChanged("FirstDue"); taskList.NotifyPropertyChanged("FirstDueColor"); }); dp.TabIndex = tabIndex++; EditStackPanel.Children.Add(dp); break; case "Boolean": CheckBox cb = new CheckBox() { DataContext = taskCopy, IsTabStop = true }; cb.SetBinding(CheckBox.IsCheckedProperty, new Binding(pi.Name) { Mode = BindingMode.TwoWay }); cb.TabIndex = tabIndex++; EditStackPanel.Children.Add(cb); break; case "TagList": TextBox taglist = new TextBox() { MinWidth = minWidth, IsTabStop = true }; taglist.KeyUp += new KeyEventHandler(TextBox_KeyUp); taglist.TabIndex = tabIndex++; RenderEditTaskTagList(taglist, taskCopy, pi); EditStackPanel.Children.Add(taglist); break; case "ListPointer": innerPanel = RenderEditTaskListPointer(pi, minWidth); EditStackPanel.Children.Add(innerPanel); break; default: notMatched = true; break; } // if wasn't able to match field type by display type, try matching by CLR type if (notMatched == true) { string typename = GetTypeName(pi); switch (typename) { case "String": tb.InputScope = new InputScope() { Names = { new InputScopeName() { NameValue = InputScopeNameValue.Text } } }; tb.LostFocus += new RoutedEventHandler(delegate { pi.SetValue(taskCopy, tb.Text, null); }); tb.TabIndex = tabIndex++; tb.KeyUp += new KeyEventHandler(TextBox_KeyUp); EditStackPanel.Children.Add(tb); break; case "Int32": tb.InputScope = new InputScope() { Names = { new InputScopeName() { NameValue = InputScopeNameValue.Digits } } }; tb.LostFocus += new RoutedEventHandler(delegate { pi.SetValue(taskCopy, Convert.ToInt32(tb.Text), null); }); tb.TabIndex = tabIndex++; tb.KeyUp += new KeyEventHandler(TextBox_KeyUp); EditStackPanel.Children.Add(tb); break; case "DateTime": DatePicker dp = new DatePicker() { DataContext = taskCopy, MinWidth = minWidth, IsTabStop = true }; dp.SetBinding(DatePicker.ValueProperty, new Binding(pi.Name) { Mode = BindingMode.TwoWay }); dp.ValueChanged += new EventHandler<DateTimeValueChangedEventArgs>(delegate { pi.SetValue(taskCopy, dp.Value, null); taskList.NotifyPropertyChanged("FirstDue"); taskList.NotifyPropertyChanged("FirstDueColor"); }); dp.TabIndex = tabIndex++; EditStackPanel.Children.Add(dp); break; case "Boolean": CheckBox cb = new CheckBox() { DataContext = taskCopy, IsTabStop = true }; cb.SetBinding(CheckBox.IsEnabledProperty, new Binding(pi.Name) { Mode = BindingMode.TwoWay }); cb.TabIndex = tabIndex++; EditStackPanel.Children.Add(cb); break; default: break; } } // add the listboxitem to the listbox EditListBox.Items.Add(listBoxItem); }