private Element RenderEditItemField(Item item, Field field) { PropertyInfo pi = null; object currentValue = null; object container = null; // get the current field value. // the value can either be in a strongly-typed property on the item (e.g. Name), // or in one of the FieldValues try { // get the strongly typed property pi = item.GetType().GetProperty(field.Name); if (pi != null) { // store current item's value for this field currentValue = pi.GetValue(item, null); // set the container - this will be the object that will be passed // to pi.SetValue() below to poke new values into container = item; } } catch (Exception) { // an exception indicates this isn't a strongly typed property on the Item // this is NOT an error condition } // if couldn't find a strongly typed property, this property is stored as a // FieldValue on the item if (pi == null) { // get current item's value for this field, or create a new FieldValue // if one doesn't already exist FieldValue fieldValue = item.GetFieldValue(field.ID, true); currentValue = fieldValue.Value; // get the value property of the current fieldvalue (this should never fail) pi = fieldValue.GetType().GetProperty("Value"); if (pi == null) return null; // set the container - this will be the object that will be passed // to pi.SetValue() below to poke new values into container = fieldValue; } // most elements will be Entry Elements - default to this EntryElement entryElement = new EntryElement(field.DisplayName, "", ""); Element element = entryElement; bool notMatched = false; // render the right control based on the type switch (field.DisplayType) { case DisplayTypes.Text: //StyledMultilineElement stringElement = new StyledMultilineElement(field.DisplayName, (string) currentValue); entryElement.KeyboardType = UIKeyboardType.Default; entryElement.Value = (string) currentValue; entryElement.AutocorrectionType = UITextAutocorrectionType.Yes; entryElement.Changed += delegate { pi.SetValue(container, entryElement.Value, null); }; //element = stringElement; break; case DisplayTypes.TextArea: MultilineEntryElement multilineElement = new MultilineEntryElement(field.DisplayName, (string) currentValue) { Lines = 3 }; multilineElement.Changed += delegate { pi.SetValue(container, multilineElement.Value, null); }; //var multilineElement = new MultilineEntryElement3(field.DisplayName, (string) currentValue) { Editable = true }; //multilineElement.Changed += delegate { pi.SetValue(container, multilineElement.Value, null); }; element = multilineElement; //entryElement.Value = (string) currentValue; //entryElement.Changed += delegate { pi.SetValue(container, entryElement.Value, null); }; break; case DisplayTypes.Phone: entryElement.Value = (string) currentValue; entryElement.KeyboardType = UIKeyboardType.PhonePad; entryElement.Changed += delegate { pi.SetValue(container, entryElement.Value, null); }; break; case DisplayTypes.Link: entryElement.Value = (string) currentValue; entryElement.KeyboardType = UIKeyboardType.Url; entryElement.Changed += delegate { pi.SetValue(container, entryElement.Value, null); }; break; case DisplayTypes.Email: entryElement.Value = (string) currentValue; entryElement.KeyboardType = UIKeyboardType.EmailAddress; entryElement.Changed += delegate { pi.SetValue(container, entryElement.Value, null); }; break; case DisplayTypes.Address: entryElement.Value = (string) currentValue; entryElement.AutocorrectionType = UITextAutocorrectionType.Yes; entryElement.Changed += delegate { pi.SetValue(container, entryElement.Value, null); }; break; case DisplayTypes.Priority: var priorities = new RadioGroup(field.DisplayName, 0); priorities.Selected = ((int?) currentValue) != null ? (int) currentValue : 1; // HACK: hardcode to "Normal" priority. this should come from a table. var priSection = new Section(); priSection.AddAll( from pr in App.ViewModel.Constants.Priorities select (Element) new RadioEventElement(pr.Name, field.DisplayName)); var priorityElement = new ThemedRootElement(field.DisplayName, priorities) { priSection }; // augment the radio elements with the right index and event handler int i = 0; foreach (var radio in priorityElement[0].Elements) { RadioEventElement radioEventElement = (RadioEventElement) radio; int index = i++; radioEventElement.OnSelected += delegate { pi.SetValue(container, index, null); }; } element = priorityElement; break; case DisplayTypes.Lists: // create a collection of lists in this folder, and add the folder as the first entry var lists = App.ViewModel.Items. Where(li => li.FolderID == item.FolderID && li.IsList == true && li.ItemTypeID != SystemItemTypes.Reference). OrderBy(li => li.Name). ToObservableCollection(); lists.Insert(0, new Item() { ID = Guid.Empty, Name = folder.Name }); // a null value for the "list" field indicates a Folder as a parent (i.e. this item is a top-level item) if (currentValue == null) currentValue = Guid.Empty; Item currentList = lists.FirstOrDefault(li => li.ID == (Guid) currentValue); var listsGroup = new RadioGroup (field.DisplayName, 0); listsGroup.Selected = Math.Max(lists.IndexOf(currentList), 0); var listsSection = new Section(); listsSection.AddAll( from l in lists select (Element) new RadioEventElement(l.Name, field.DisplayName)); var listsElement = new ThemedRootElement(field.DisplayName, listsGroup) { listsSection }; // augment the radio elements with the right index and event handler int index = 0; foreach (var radio in listsElement[0].Elements) { int currentIndex = index; // make a local copy for the closure RadioEventElement radioEventElement = (RadioEventElement) radio; radioEventElement.OnSelected += delegate(object sender, EventArgs e) { pi.SetValue(container, lists[currentIndex].ID, null); }; index++; } element = listsElement; break; case DisplayTypes.DatePicker: DateTime? dateTime = String.IsNullOrEmpty((string) currentValue) ? (DateTime?) null : Convert.ToDateTime((string) currentValue); DateEventElement dateElement = new DateEventElement(field.DisplayName, dateTime); dateElement.ValueSelected += delegate { pi.SetValue(container, ((DateTime)dateElement.DateValue).ToString("yyyy/MM/dd"), null); folder.NotifyPropertyChanged("FirstDue"); folder.NotifyPropertyChanged("FirstDueColor"); }; element = dateElement; break; case DisplayTypes.DateTimePicker: DateTime? dt = String.IsNullOrEmpty((string) currentValue) ? (DateTime?) null : Convert.ToDateTime((string) currentValue); DateTimeEventElement dateTimeElement = new DateTimeEventElement(field.DisplayName, dt); dateTimeElement.ValueSelected += (s, e) => { pi.SetValue(container, dateTimeElement.DateValue == null ? null : ((DateTime) dateTimeElement.DateValue).ToString(), null); folder.NotifyPropertyChanged("FirstDue"); folder.NotifyPropertyChanged("FirstDueColor"); }; element = dateTimeElement; break; case DisplayTypes.Checkbox: CheckboxElement checkboxElement = new CheckboxElement(field.DisplayName, currentValue == null ? false : (bool) currentValue); checkboxElement.Tapped += delegate { pi.SetValue(container, checkboxElement.Value, null); }; element = checkboxElement; break; case DisplayTypes.TagList: // TODO element = null; break; case DisplayTypes.ImageUrl: // TODO: wire up to picture picker, and upload to an image service element = null; break; case DisplayTypes.LinkArray: var linkArrayElement = new MultilineEntryElement(field.DisplayName, (string) currentValue) { Lines = 3, AcceptReturns = true }; if (!String.IsNullOrEmpty((string) currentValue)) { try { var linkList = JsonConvert.DeserializeObject<List<Link>>((string)currentValue); linkArrayElement.Value = String.Concat(linkList.Select(l => l.Name != null ? l.Name + "," + l.Url + "\n" : l.Url + "\n").ToList()); } catch (Exception) { } } linkArrayElement.Changed += delegate { // the expected format is a newline-delimited list of Name, Url pairs var linkArray = linkArrayElement.Value.Split(new char[] { '\r','\n' }, StringSplitOptions.RemoveEmptyEntries); var linkList = new List<Link>(); foreach (var link in linkArray) { var nameval = link.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (nameval.Length == 0) continue; if (nameval.Length == 1) linkList.Add(new Link() { Url = nameval[0].Trim() }); else linkList.Add(new Link() { Name = nameval[0].Trim(), Url = nameval[1].Trim() }); } var json = JsonConvert.SerializeObject(linkList); pi.SetValue(container, json, null); }; element = linkArrayElement; break; case DisplayTypes.Hidden: // skip rendering element = null; break; case DisplayTypes.ContactList: StringElement contactsElement = new StringElement(field.DisplayName); Item currentContacts = CreateValueList(item, field, currentValue == null ? Guid.Empty : new Guid((string) currentValue)); contactsElement.Value = CreateCommaDelimitedList(currentContacts); Item contacts = new Item() { Items = App.ViewModel.Items. Where(it => it.ItemTypeID == SystemItemTypes.Contact && it.IsList == false). Select(it => new Item() { Name = it.Name, FolderID = folder.ID, ItemTypeID = SystemItemTypes.Reference, ParentID = currentContacts.ID, ItemRef = it.ID }). ToObservableCollection(), }; contactsElement.Tapped += delegate { // put up the list picker dialog ListPickerPage listPicker = new ListPickerPage( SystemItemTypes.Contact, editViewController.NavigationController, contactsElement, pi, container, field.DisplayName, currentContacts, contacts); listPicker.PushViewController(); }; element = contactsElement; break; case DisplayTypes.LocationList: StringElement locationsElement = new StringElement(field.DisplayName); Item currentLocations = CreateValueList(item, field, currentValue == null ? Guid.Empty : new Guid((string) currentValue)); locationsElement.Value = CreateCommaDelimitedList(currentLocations); Item locations = new Item() { Items = App.ViewModel.Items. Where(it => it.ItemTypeID == SystemItemTypes.Location && it.IsList == false). Select(it => new Item() { Name = it.Name, FolderID = folder.ID, ItemTypeID = SystemItemTypes.Reference, ParentID = currentLocations.ID, ItemRef = it.ID }). ToObservableCollection(), }; locationsElement.Tapped += delegate { // put up the list picker dialog ListPickerPage listPicker = new ListPickerPage( SystemItemTypes.Location, editViewController.NavigationController, locationsElement, pi, container, field.DisplayName, currentLocations, locations); listPicker.PushViewController(); }; element = locationsElement; break; case DisplayTypes.ItemTypes: var itemTypePickerElement = new ItemTypePickerElement("Type", (Guid) currentValue); itemTypePickerElement.OnSelected += (sender, e) => { pi.SetValue(container, itemTypePickerElement.SelectedItemType, null); }; element = itemTypePickerElement; break; default: notMatched = true; break; } // if wasn't able to match field type by display type, try matching by FieldType if (notMatched == true) { switch (field.FieldType) { case FieldTypes.String: default: entryElement.KeyboardType = UIKeyboardType.Default; entryElement.Value = (string) currentValue; entryElement.AutocorrectionType = UITextAutocorrectionType.Yes; entryElement.Changed += delegate { pi.SetValue(container, entryElement.Value, null); }; break; case FieldTypes.Integer: entryElement.Value = (string) currentValue; entryElement.KeyboardType = UIKeyboardType.NumberPad; entryElement.Changed += delegate { pi.SetValue(container, entryElement.Value, null); }; break; case FieldTypes.DateTime: DateTime dateTime = currentValue == null ? DateTime.Now.Date : Convert.ToDateTime ((string) currentValue); DateEventElement dateElement = new DateEventElement(field.DisplayName, dateTime); dateElement.ValueSelected += delegate { pi.SetValue(container, ((DateTime)dateElement.DateValue).ToString("yyyy/MM/dd"), null); folder.NotifyPropertyChanged("FirstDue"); folder.NotifyPropertyChanged("FirstDueColor"); }; element = dateElement; break; case FieldTypes.Boolean: CheckboxElement checkboxElement = new CheckboxElement(field.DisplayName, currentValue == null ? false : (bool) currentValue); checkboxElement.Tapped += delegate { pi.SetValue(container, checkboxElement.Value, null); }; element = checkboxElement; break; } } return element; }
private RootElement InitializeAccountSettings() { user = App.ViewModel.User; ThemedRootElement accountRootElement = null; // initialize the Account element based on whether connected or disconnected if (IsConnected) { // initialize account controls Email = new StringElement("Email", user.Email); // create unicode bullet characters for every character in the password var sb = new StringBuilder(); if (user != null && user.Password != null) foreach (var c in user.Password) sb.Append("\u25CF"); // \u2022 Password = new StringElement("Password", sb.ToString()); // create buttons var button = new ButtonListElement() { new Button() { Caption = "Disconnect", Background = "Images/darkgreybutton.png", Clicked = DisconnectUserButton_Click }, }; button.Margin = 0f; // create the account root element accountRootElement = new ThemedRootElement("Account") { new Section() { Email, Password, }, new Section() { button } }; } else { // initialize account controls Email = new EntryElement("Email", "Enter email", user != null ? user.Email : null); Password = new EntryElement("Password", "Enter password", user != null ? user.Password : null, true); var createButton = new ButtonListElement() { new Button() { Caption = "Create a new account", Background = "Images/darkgreybutton.png", Clicked = CreateUserButton_Click }, }; createButton.Margin = 0f; var connectButton = new ButtonListElement() { new Button() { Caption = "Connect to an existing account", Background = "Images/darkgreybutton.png", Clicked = ConnectUserButton_Click }, }; connectButton.Margin = 0f; // create the account root element accountRootElement = new ThemedRootElement("Account") { new Section() { Email, Password, }, new Section() { createButton, }, new Section() { connectButton } }; } return accountRootElement; }
private UIBarButtonItem CreateSortButton() { // if haven't loaded the sort image yet, do so now if (sortButtonImage == null) sortButtonImage = UIImageCache.GetUIImage("Images/appbar.sort.rest.png"); // clicking the sort button and its event handler, which creates a new DialogViewController to host the sort picker var sortButton = new UIBarButtonItem(sortButtonImage, UIBarButtonItemStyle.Plain, delegate { // create the remove button var removeButton = new Button() { Caption = "Remove Sort", Background = "Images/darkgreybutton.png", }; var removeButtonList = new ButtonListElement() { removeButton }; removeButtonList.Margin = 0f; // find the current sort field if any var itemType = App.ViewModel.ItemTypes.Single(it => it.ID == Source.List.ItemTypeID); var fields = itemType.Fields.Where(f => f.IsPrimary == true).ToList(); var selectedSortIndex = 0; if (Source.OrderBy != null && fields.Any(f => f.DisplayName == Source.OrderBy)) { var selectedSortField = fields.Single(f => f.DisplayName == Source.OrderBy); selectedSortIndex = Math.Max(fields.IndexOf(selectedSortField), 0); } // create the sort picker var sortPickerSection = new Section(); sortPickerSection.AddAll(from f in fields select (Element) new RadioElement(f.DisplayName)); var sortPicker = new ThemedRootElement("Sort by", new RadioGroup(null, selectedSortIndex)) { sortPickerSection }; // create the "Choose Sort" form var root = new ThemedRootElement("Choose Sort") { new Section() { sortPicker }, new Section() { removeButtonList }, }; // create the DVC and add a "Done" button and handler var dvc = new DialogViewController(root); dvc.NavigationItem.RightBarButtonItem = new UIBarButtonItem(UIBarButtonSystemItem.Done, delegate { // store the current listbox and orderby field, and re-render the list var field = fields[sortPicker.RadioSelected]; Source.OrderBy = field.Name; // store the sort order ListMetadataHelper.StoreListSortOrder( App.ViewModel.PhoneClientFolder, Source.List.ID == Guid.Empty ? (ClientEntity) Source.Folder : (ClientEntity) Source.List, Source.OrderBy); // sync with the service // (do not sync for operations against $ClientSettings) //App.ViewModel.SyncWithService(); // return to parent dvc.NavigationController.PopViewControllerAnimated(true); }); dvc.TableView.BackgroundColor = UIColorHelper.FromString(App.ViewModel.Theme.PageBackground); // add the click handler for the remove button removeButton.Clicked += delegate { // clear the sort Source.OrderBy = null; // store the sort order ListMetadataHelper.StoreListSortOrder( App.ViewModel.PhoneClientFolder, Source.List.ID == Guid.Empty ? (ClientEntity) Source.Folder : (ClientEntity) Source.List, null); // sync with the service // (do not sync for operations against $ClientSettings) //App.ViewModel.SyncWithService(); // return to parent dvc.NavigationController.PopViewControllerAnimated(true); }; // display the form this.NavigationController.PushViewController(dvc, true); }); return sortButton; }