/// <summary> /// Generate the controls based upon the control descriptions found in the template /// </summary>> public void CreateControls(FileDatabase database, DataEntryHandler dataEntryPropagator) { // Check the arguments for null ThrowIf.IsNullArgument(dataEntryPropagator, nameof(dataEntryPropagator)); ThrowIf.IsNullArgument(database, nameof(database)); // Depending on how the user interacts with the file import process image set loading can be aborted after controls are generated and then // another image set loaded. Any existing controls therefore need to be cleared. this.Controls.Clear(); this.ControlsByDataLabel.Clear(); this.ControlGrid.Inlines.Clear(); foreach (ControlRow control in database.Controls) { // no point in generating a control if it doesn't render in the UX if (control.Visible == false) { continue; } DataEntryControl controlToAdd; if (control.Type == Constant.DatabaseColumn.DateTime) { DataEntryDateTime dateTimeControl = new DataEntryDateTime(control, this); controlToAdd = dateTimeControl; } else if (control.Type == Constant.DatabaseColumn.File || control.Type == Constant.DatabaseColumn.RelativePath || control.Type == Constant.DatabaseColumn.Folder || control.Type == Constant.DatabaseColumn.Date || control.Type == Constant.DatabaseColumn.Time || control.Type == Constant.Control.Note) { // standard controls rendering as notes aren't editable by the user, so we don't need autocompletions on tht Dictionary <string, string> autocompletions = null; bool readOnly = control.Type != Constant.Control.Note; if (readOnly == false) { autocompletions = new Dictionary <string, string>(); } DataEntryNote noteControl = new DataEntryNote(control, autocompletions, this) { ContentReadOnly = readOnly }; controlToAdd = noteControl; } else if (control.Type == Constant.Control.Flag || control.Type == Constant.DatabaseColumn.DeleteFlag) { DataEntryFlag flagControl = new DataEntryFlag(control, this); controlToAdd = flagControl; } else if (control.Type == Constant.Control.Counter) { DataEntryCounter counterControl = new DataEntryCounter(control, this); controlToAdd = counterControl; } else if (control.Type == Constant.Control.FixedChoice) { DataEntryChoice choiceControl = new DataEntryChoice(control, this); controlToAdd = choiceControl; } else if (control.Type == Constant.DatabaseColumn.ImageQuality) { DataEntryChoice choiceControl = new DataEntryChoice(control, this); choiceControl.HideItems(new List <string> { FileSelectionEnum.Corrupted.ToString(), FileSelectionEnum.Missing.ToString() }); controlToAdd = choiceControl; } else if (control.Type == Constant.DatabaseColumn.UtcOffset) { DataEntryUtcOffset utcOffsetControl = new DataEntryUtcOffset(control, this) { ContentReadOnly = true }; controlToAdd = utcOffsetControl; } else { TracePrint.PrintMessage(String.Format("Unhandled control type {0} in CreateControls.", control.Type)); continue; } this.ControlGrid.Inlines.Add(controlToAdd.Container); this.Controls.Add(controlToAdd); this.ControlsByDataLabel.Add(control.DataLabel, controlToAdd); } // Redundant check as for some reason CA1062 was still showing up as a warning. ThrowIf.IsNullArgument(dataEntryPropagator, nameof(dataEntryPropagator)); dataEntryPropagator.SetDataEntryCallbacks(this.ControlsByDataLabel); this.dataEntryHandler = dataEntryPropagator; }
/// <summary> /// Add data event handler callbacks for (possibly invisible) controls /// </summary> public void SetDataEntryCallbacks(Dictionary <string, DataEntryControl> controlsByDataLabel) { // Check the arguments for null ThrowIf.IsNullArgument(controlsByDataLabel, nameof(controlsByDataLabel)); // Add data entry callbacks to all editable controls. When the user changes a file's attribute using a particular control, // the callback updates the matching field for that file in the database. foreach (KeyValuePair <string, DataEntryControl> pair in controlsByDataLabel) { //if (pair.Value.ContentReadOnly) //{ // continue; //} string controlType = this.FileDatabase.FileTableColumnsByDataLabel[pair.Key].ControlType; switch (controlType) { case Constant.Control.Note: case Constant.DatabaseColumn.File: case Constant.DatabaseColumn.Folder: case Constant.DatabaseColumn.RelativePath: DataEntryNote note = (DataEntryNote)pair.Value; note.ContentControl.TextAutocompleted += this.NoteControl_TextAutocompleted; //if (controlType == Constant.Control.Note) //{ this.SetContextMenuCallbacks(note); //} break; case Constant.DatabaseColumn.Date: case Constant.DatabaseColumn.Time: DataEntryNote datetimeNote = (DataEntryNote)pair.Value; datetimeNote.ContentControl.TextAutocompleted += this.NoteControl_TextAutocompleted; if (controlType == Constant.Control.Note) { this.SetContextMenuCallbacks(datetimeNote); } break; case Constant.DatabaseColumn.DateTime: // SAULXXX There are several issues with the XCEED DateTimePicker. In particular, the date in the // text date area is not well coordinated with the date in the calendar, i.e., the two aren't necessarily in // sync. As well, changing a date on the calendar doesnt' appear to trigger the DateTimeContro_ValueChanged event // Various workarounds are implemented as commented below with SAULXXX DateTimePicker Workaround. // If the toolkit is updated to fix them, then those workarounds can be deleted (but test them first). DataEntryDateTime dateTime = (DataEntryDateTime)pair.Value; dateTime.ContentControl.ValueChanged += this.DateTimeControl_ValueChanged; // We need the lines below as otherwise it will show the panel's context menu, which is confusing, instead of nothing dateTime.ContentControl.ContextMenu = new ContextMenu { Visibility = Visibility.Collapsed }; // SAULXXX DateTimePicker Workaround. // We need to access the calendar part of the DateTImePicker, but // we can't do that until the control is loaded. dateTime.ContentControl.Loaded += this.DateTimePicker_Loaded; break; case Constant.DatabaseColumn.UtcOffset: DataEntryUtcOffset utcOffset = (DataEntryUtcOffset)pair.Value; utcOffset.ContentControl.ValueChanged += this.UtcOffsetControl_ValueChanged; // We need the lines below as otherwise it will show the panel's context menu, which is confusing, instead of nothing utcOffset.ContentControl.ContextMenu = new ContextMenu { Visibility = Visibility.Collapsed }; break; case Constant.DatabaseColumn.DeleteFlag: case Constant.Control.Flag: DataEntryFlag flag = (DataEntryFlag)pair.Value; flag.ContentControl.Checked += this.FlagControl_CheckedChanged; flag.ContentControl.Unchecked += this.FlagControl_CheckedChanged; this.SetContextMenuCallbacks(flag); break; case Constant.DatabaseColumn.ImageQuality: case Constant.Control.FixedChoice: DataEntryChoice choice = (DataEntryChoice)pair.Value; choice.ContentControl.SelectionChanged += this.ChoiceControl_SelectionChanged; this.SetContextMenuCallbacks(choice); break; case Constant.Control.Counter: DataEntryCounter counter = (DataEntryCounter)pair.Value; counter.ContentControl.ValueChanged += this.CounterControl_ValueChanged; this.SetContextMenuCallbacks(counter); break; default: break; } } }