// Menu selections for propagating or copying the current value of this control to all images

        // Copy the last non-empty value in this control preceding this file up to the current image
        protected virtual void MenuItemPropagateFromLastValue_Click(object sender, RoutedEventArgs e)
        {
            // Check the arguments for null
            ThrowIf.IsNullArgument(sender, nameof(sender));

            // Get the chosen data entry control
            DataEntryControl control = (DataEntryControl)((MenuItem)sender).Tag;

            if (control == null)
            {
                return;
            }

            bool     checkForZero    = control is DataEntryCounter;
            bool     isFlag          = control is DataEntryFlag;
            int      indexToCopyFrom = -1;
            ImageRow valueSource     = null;
            string   valueToCopy     = checkForZero ? "0" : String.Empty;

            // Search for the row with some value in it, starting from the previous row
            int currentRowIndex = (this.ThumbnailGrid.IsVisible == false) ? this.ImageCache.CurrentRow : this.ThumbnailGrid.GetSelected()[0];

            for (int previousIndex = currentRowIndex - 1; previousIndex >= 0; previousIndex--)
            {
                ImageRow file = this.FileDatabase.FileTable[previousIndex];
                if (file == null)
                {
                    continue;
                }
                valueToCopy = file.GetValueDatabaseString(control.DataLabel);
                if (valueToCopy == null)
                {
                    continue;
                }
                valueToCopy = valueToCopy.Trim();
                if (valueToCopy.Length > 0)
                {
                    if ((checkForZero && !valueToCopy.Equals("0")) ||                                                       // Skip over non-zero values for counters
                        (isFlag && !valueToCopy.Equals(Constant.BooleanValue.False, StringComparison.OrdinalIgnoreCase)) || // Skip over false values for flags
                        (!checkForZero && !isFlag))
                    {
                        indexToCopyFrom = previousIndex;    // We found a non-empty value
                        valueSource     = file;
                        break;
                    }
                }
            }

            string newContent = valueToCopy;

            if (indexToCopyFrom < 0)
            {
                // Display a dialog box saying there is nothing to propagate.
                // Note that this should never be displayed, as the menu shouldn't be highlit if there is nothing to propagate
                // But just in case...
                Dialogs.DataEntryNothingToPropagateDialog(Application.Current.MainWindow);
                return;
            }

            // Display the appropriate dialog box that explains what will happen. Arguments indicate what is to be propagated and how many files will be affected
            int filesAffected = currentRowIndex - indexToCopyFrom;

            if (Dialogs.DataEntryConfirmPropagateFromLastValueDialog(Application.Current.MainWindow, valueToCopy, filesAffected) != true)
            {
                return; // operation cancelled
                // newContent = this.FileDatabase.FileTable[currentRowIndex].GetValueDisplayString(control.DataLabel); // No change, so return the current value
            }

            // Update the affected files. Note that we start on the row after the one with a value in it to the current row.
            Mouse.OverrideCursor = Cursors.Wait;
            this.FileDatabase.UpdateFiles(valueSource, control.DataLabel, indexToCopyFrom + 1, currentRowIndex);
            control.SetContentAndTooltip(newContent);
            Mouse.OverrideCursor = null;
        }