public static bool TryFindFocusedControl(IInputElement focusedElement, out DataEntryControl focusedControl)
        {
            if (focusedElement is FrameworkElement)
            {
                FrameworkElement focusedFrameworkElement = (FrameworkElement)focusedElement;
                focusedControl = (DataEntryControl)focusedFrameworkElement.Tag;
                if (focusedControl != null)
                {
                    return true;
                }

                // for complex controls which dynamic generate child controls, such as date time pickers, the tag of the focused element can't be set
                // so try to locate a parent of the focused element with a tag indicating the control
                FrameworkElement parent = null;
                if (focusedFrameworkElement.Parent != null && focusedFrameworkElement.Parent is FrameworkElement)
                {
                    parent = (FrameworkElement)focusedFrameworkElement.Parent;
                }
                else if (focusedFrameworkElement.TemplatedParent != null && focusedFrameworkElement.TemplatedParent is FrameworkElement)
                {
                    parent = (FrameworkElement)focusedFrameworkElement.TemplatedParent;
                }

                if (parent != null)
                {
                    return DataEntryHandler.TryFindFocusedControl(parent, out focusedControl);
                }
            }

            focusedControl = null;
            return false;
        }
        /// <summary>Propagate the current value of this control forward from this point across the current selection.</summary>
        public void CopyForward(DataEntryControl control, bool checkForZeroValue)
        {
            int filesAffected = this.FileDatabase.CurrentlySelectedFileCount - this.ImageCache.CurrentRow - 1;
            if (filesAffected == 0)
            {
                // should be unreachable as the menu shouldn't be be enabled on the last file
                MessageBox messageBox = new MessageBox("Nothing to copy forward.", Application.Current.MainWindow);
                messageBox.Message.Reason = "As you are on the last file, there are no files after this.";
                messageBox.ShowDialog();
                return;
            }

            string valueToCopy = this.ImageCache.Current.GetValueDisplayString(control);
            if (this.ConfirmCopyForward(valueToCopy, filesAffected, checkForZeroValue) != true)
            {
                return;
            }

            // update starts on the next row since copying from the current row
            this.FileDatabase.UpdateFiles(this.ImageCache.Current, control, this.ImageCache.CurrentRow + 1, this.FileDatabase.CurrentlySelectedFileCount - 1);
        }
        private void SetPropagateContextMenu(DataEntryControl control)
        {
            MenuItem menuItemPropagateFromLastValue = new MenuItem();
            menuItemPropagateFromLastValue.IsCheckable = false;
            menuItemPropagateFromLastValue.Header = "Propagate from the _last non-empty value to here...";
            if (control is DataEntryCounter)
            {
                menuItemPropagateFromLastValue.Header = "Propagate from the _last non-zero value to here...";
            }
            menuItemPropagateFromLastValue.Click += this.MenuItemPropagateFromLastValue_Click;
            menuItemPropagateFromLastValue.Tag = control;

            MenuItem menuItemCopyForward = new MenuItem();
            menuItemCopyForward.IsCheckable = false;
            menuItemCopyForward.Header = "Copy forward to _end...";
            menuItemCopyForward.ToolTip = "The value of this field will be copied forward from this file to the last file in this set";
            menuItemCopyForward.Click += this.MenuItemPropagateForward_Click;
            menuItemCopyForward.Tag = control;

            MenuItem menuItemCopyCurrentValue = new MenuItem();
            menuItemCopyCurrentValue.IsCheckable = false;
            menuItemCopyCurrentValue.Header = "Copy to _all...";
            menuItemCopyCurrentValue.Click += this.MenuItemCopyCurrentValue_Click;
            menuItemCopyCurrentValue.Tag = control;

            // DataEntrHandler.PropagateFromLastValueIndex and CopyForwardIndex must be kept in sync with the add order here
            ContextMenu menu = new ContextMenu();
            menu.Items.Add(menuItemPropagateFromLastValue);
            menu.Items.Add(menuItemCopyForward);
            menu.Items.Add(menuItemCopyCurrentValue);

            control.Container.ContextMenu = menu;
            control.Container.PreviewMouseRightButtonDown += this.Container_PreviewMouseRightButtonDown;

            if (control is DataEntryCounter)
            {
                DataEntryCounter counter = (DataEntryCounter)control;
                counter.ContentControl.ContextMenu = menu;
            }
            else if (control is DataEntryNote)
            {
                DataEntryNote note = (DataEntryNote)control;
                note.ContentControl.ContextMenu = menu;
            }
            else if (control is DataEntryChoice)
            {
                DataEntryChoice choice = (DataEntryChoice)control;
                choice.ContentControl.ContextMenu = menu;
            }
            else if (control is DataEntryFlag)
            {
                DataEntryFlag flag = (DataEntryFlag)control;
                flag.ContentControl.ContextMenu = menu;
            }
            else
            {
                throw new NotSupportedException(String.Format("Unhandled control type {0}.", control.GetType().Name));
            }
        }
        public bool IsCopyForwardPossible(DataEntryControl control)
        {
            if (this.ImageCache.Current == null || control.Copyable == false)
            {
                return false;
            }

            int imagesAffected = this.FileDatabase.CurrentlySelectedFileCount - this.ImageCache.CurrentRow - 1;
            return (imagesAffected > 0) ? true : false;
        }
 // Return true if there is a non-empty value available
 public bool IsCopyFromLastNonEmptyValuePossible(DataEntryControl control)
 {
     bool checkForZero = control is DataEntryCounter;
     int nearestRowWithCopyableValue = -1;
     for (int fileIndex = this.ImageCache.CurrentRow - 1; fileIndex >= 0; --fileIndex)
     {
         // Search for the row with some value in it, starting from the previous row
         string valueToCopy = this.FileDatabase.Files[fileIndex].GetValueDatabaseString(control.DataLabel);
         if (String.IsNullOrWhiteSpace(valueToCopy) == false)
         {
             if ((checkForZero && !valueToCopy.Equals("0")) || !checkForZero)
             {
                 nearestRowWithCopyableValue = fileIndex;    // found a non-empty value
                 break;
             }
         }
     }
     return (nearestRowWithCopyableValue >= 0) ? true : false;
 }
 /// <summary>Copy the current value of this control to all images</summary>
 public void CopyToAll(DataEntryControl control)
 {
     bool checkForZero = control is DataEntryCounter;
     int imagesAffected = this.FileDatabase.CurrentlySelectedFileCount;
     string displayValueToCopy = this.ImageCache.Current.GetValueDisplayString(control);
     if (this.ConfirmCopyCurrentValueToAll(displayValueToCopy, imagesAffected, checkForZero) != true)
     {
         return;
     }
     this.FileDatabase.UpdateFiles(this.ImageCache.Current, control);
 }
        /// <summary>
        /// Copy the last non-empty value in this control preceding this file up to the current file
        /// </summary>
        public string CopyFromLastNonEmptyValue(DataEntryControl control)
        {
            bool isCounter = control is DataEntryCounter;
            bool isFlag = control is DataEntryFlag;

            ImageRow fileWithLastNonEmptyValue = null;
            int indexToCopyFrom = Constant.Database.InvalidRow;
            string valueToCopy = isCounter ? "0" : String.Empty;
            for (int previousIndex = this.ImageCache.CurrentRow - 1; previousIndex >= 0; previousIndex--)
            {
                // Search for the row with some value in it, starting from the previous row
                ImageRow file = this.FileDatabase.Files[previousIndex];
                valueToCopy = file.GetValueDatabaseString(control.DataLabel);
                if (valueToCopy == null)
                {
                    continue;
                }

                valueToCopy = valueToCopy.Trim();
                if (valueToCopy.Length > 0)
                {
                    if ((isCounter && !valueToCopy.Equals("0")) ||                                               // skip zero values for counters
                        (isFlag && !valueToCopy.Equals(Boolean.FalseString, StringComparison.OrdinalIgnoreCase)) || // false values for flags are considered empty
                        (!isCounter && !isFlag))
                    {
                        indexToCopyFrom = previousIndex;
                        fileWithLastNonEmptyValue = file;
                        break;
                    }
                }
            }

            if (indexToCopyFrom == Constant.Database.InvalidRow)
            {
                // Nothing to propagate.  If the menu item is deactivated as expected this shouldn't be reachable.
                MessageBox messageBox = new MessageBox("Nothing to propagate to here.", Application.Current.MainWindow);
                messageBox.Message.Reason = "None of the earlier files have anything in this field, so there are no values to propagate.";
                messageBox.ShowDialog();
                return this.FileDatabase.Files[this.ImageCache.CurrentRow].GetValueDisplayString(control); // No change, so return the current value
            }

            int imagesAffected = this.ImageCache.CurrentRow - indexToCopyFrom;
            if (this.ConfirmPropagateFromLastValue(valueToCopy, imagesAffected) != true)
            {
                return this.FileDatabase.Files[this.ImageCache.CurrentRow].GetValueDisplayString(control); // No change, so return the current value
            }

            this.FileDatabase.UpdateFiles(fileWithLastNonEmptyValue, control, indexToCopyFrom + 1, this.ImageCache.CurrentRow);
            return valueToCopy;
        }
 public string GetValueDisplayString(DataEntryControl control)
 {
     switch (control.DataLabel)
     {
         case Constant.DatabaseColumn.DateTime:
             return this.GetDisplayDateTime();
         case Constant.DatabaseColumn.ID:
             return this.ID.ToString();
         case Constant.DatabaseColumn.ImageQuality:
             return this.ImageQuality.ToString();
         case Constant.DatabaseColumn.UtcOffset:
             return DateTimeHandler.ToDisplayUtcOffsetString(this.UtcOffset);
         default:
             return this.Row.GetStringField(control.DataLabel);
     }
 }
        public void UpdateFiles(ImageRow valueSource, DataEntryControl control, int fromIndex, int toIndex)
        {
            if (fromIndex < 0)
            {
                throw new ArgumentOutOfRangeException("fromIndex");
            }
            if (toIndex < fromIndex || toIndex > this.CurrentlySelectedFileCount - 1)
            {
                throw new ArgumentOutOfRangeException("toIndex");
            }

            string value = valueSource.GetValueDatabaseString(control.DataLabel);
            List<ColumnTuplesWithWhere> imagesToUpdate = new List<ColumnTuplesWithWhere>();
            for (int index = fromIndex; index <= toIndex; index++)
            {
                // update data table
                ImageRow image = this.Files[index];
                image.SetValueFromDatabaseString(control.DataLabel, value);

                // update database
                List<ColumnTuple> columnToUpdate = new List<ColumnTuple>() { new ColumnTuple(control.DataLabel, value) };
                ColumnTuplesWithWhere imageUpdate = new ColumnTuplesWithWhere(columnToUpdate, image.ID);
                imagesToUpdate.Add(imageUpdate);
            }

            this.CreateBackupIfNeeded();
            this.Database.Update(Constant.DatabaseTable.FileData, imagesToUpdate);
        }
 // Set one property on all rows in the selection to a given value
 public void UpdateFiles(ImageRow valueSource, DataEntryControl control)
 {
     this.UpdateFiles(valueSource, control, 0, this.CurrentlySelectedFileCount - 1);
 }