Repository: veler/DevToys
File: src/dev/impl/DevToys/UI/Controls/CustomTextBox.xaml.cs (C#)

Code before:

        private TextBox GetTextBox()
        {
            return (TextBox)(TextBox ?? FindName(nameof(TextBox)));
        }

        private RichEditBox GetRichEditBox()
        {
            return (RichEditBox)(RichEditBox ?? FindName(nameof(RichEditBox)));
        }
        private Button GetRefreshButton()
        {
            return (Button)(RefreshButton ?? FindName(nameof(RefreshButton)));
        }

        #region Refresh button click handler delegate

        public delegate void CustomTextBoxClickHandler(object sender, RoutedEventArgs e);

        public event CustomTextBoxClickHandler RefreshClickHandler;

        private void RefreshButton_Click(object sender, RoutedEventArgs e)
        {
            if (RefreshClickHandler is not null)
            {
                RefreshClickHandler(sender, e);
            }
        }

        #endregion Refresh button click handler delegate

        private void CopyTextBoxSelectionToClipboard()
        {
            try
            {
                var dataPackage = new DataPackage { RequestedOperation = DataPackageOperation.Copy };
                dataPackage.SetText(TextBox.SelectedText);
                Clipboard.SetContentWithOptions(dataPackage, new ClipboardContentOptions() { IsAllowedInHistory = true, IsRoamable = true });
                Clipboard.Flush(); // This method allows the content to remain available after the application shuts down.
            }
            catch (Exception ex)
            {
                Logger.LogFault("Failed to copy from custom text box", ex);
            }
        }

        private void CopyRichEditBoxSelectionToClipboard()
        {
            try
            {
                RichEditBox.Document.Selection.GetText(TextGetOptions.UseCrlf, out string? text);

Review comment (suggestion):
I'm not fan of using an Event, because it means that to know when a click happens on this control, we have to pass through the code behind the view (`LoremIpsumGeneratorToolPage.xaml.cs`). This is actually an anti-pattern in MVVM implementation.

A better approach is to use a Command. For this, you can create, in this class, a `ICommand RefreshCommand` property (and its associated `Dependency Property`).
Then, when clicking on the button, you can do something like:

```
if (RefreshCommand.CanExecute())
{
    RefreshCommand.Execute();
}
```

Finally, in `LoremIpsumGeneratorToolPage.xaml`, you can bind the property `RefreshCommand` directly to a `RelayCommand`, like we do in Guid Generator:

https://github.com/veler/DevToys/blob/8a17b71dc4cd2dae451056e3cd0e4617a04f4cbe/src/dev/impl/DevToys/ViewModels/Tools/Generators/GuidGenerator/GuidGeneratorToolViewModel.cs#L147-L154

What do you think of? :)

Code after:


        private void RefreshButton_Click(object sender, RoutedEventArgs e)
        {
            if (RefreshCommand is not null && RefreshCommand.CanExecute(e))
            {
                RefreshCommand.Execute(e);
            }
        }

        #endregion Refresh button click handler delegate

        private void CopyTextBoxSelectionToClipboard()
        {
            try
            {
                var dataPackage = new DataPackage { RequestedOperation = DataPackageOperation.Copy };
                dataPackage.SetText(TextBox.SelectedText);
                Clipboard.SetContentWithOptions(dataPackage, new ClipboardContentOptions() { IsAllowedInHistory = true, IsRoamable = true });
                Clipboard.Flush(); // This method allows the content to remain available after the application shuts down.
            }
            catch (Exception ex)
            {
                Logger.LogFault("Failed to copy from custom text box", ex);
            }
        }

        private void CopyRichEditBoxSelectionToClipboard()
        {
            try
            {
                RichEditBox.Document.Selection.GetText(TextGetOptions.UseCrlf, out string? text);
                var dataPackage = new DataPackage { RequestedOperation = DataPackageOperation.Copy };
                dataPackage.SetText(text);
                Clipboard.SetContentWithOptions(dataPackage, new ClipboardContentOptions() { IsAllowedInHistory = true, IsRoamable = true });
                Clipboard.Flush(); // This method allows the content to remain available after the application shuts down.
            }
            catch (Exception ex)
            {
                Logger.LogFault("Failed to copy from custom text box", ex);
            }
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            UpdateUI();
        }

        private void OnActualThemeChanged(FrameworkElement sender, object args)
        {
            SetHighlights(_highlightedSpans);