Blazor FlexGrid: Events for Clipboard Support needed (Cut-Copy-Paste Events)

Posted by: benjamin.koerber on 24 October 2023, 10:59 pm EST

    • Post Options:
    • Link

    Posted 24 October 2023, 10:59 pm EST

    Blazor FlexGrid supports clipboard events such as Cut, Copy, and Paste (Ctrl-X, Ctrl-C, and Ctrl-V).

    Unfortunately however, corresponding events have not been supplied - namely:

    • OnBeforeCopy & OnAfterCopy (aka CellCopyStared & CellCopyEnded)
    • OnBeforeCut & OnAfterCut
    • OnBeforePaste & OnAfterPaste

    This shortcoming cannot even be mildly compensated by wrapping the FlexGrid with a div event handler such as the following, because the edit events within the FlexGrid get badly corrupted (either editing is not possible at all, or editing gets “undone” immediately … sometimes however, editing will be successful if you are really quick!):

    <div @onkeydown="@OnKeyDownHandler">
    	    <FlexGrid ItemsSource="@_someDataArray" 
                          StyleKind="@GridStyle.Classic"
    		      Style="@("max-height:50vh")" />
    </div>
    
    @code{
        protected void OnKeyDownHandler(KeyboardEventArgs e)
        {
            if ("KeyC" == e.Code)
            {
               // React to Ctrl-C event
    	   // ...
            }
            else if ("KeyV" == e.Code)
            {
               // React to Ctrl-V event
    	   // ...
            }
        }
    }

    Therefore, I’d like to see the mentioned 6 new events could be provided for.

    If I am not entirely mistaken, the implementation would be pretty straight forward:

    New Pseudo-Code for “Copy”-Event:

    	//
    	// Summary:
    	//     Occurs before copy of a cellrange is stared.
    	[Parameter]
    	public EventHandler<GridCellClipboardEventArgs> CellCopyStarted { get; set; }
    
    	//
    	// Summary:
    	//     Occurs after copy of a cellrange is ended/committed.
    	[Parameter]
    	public EventHandler<GridCellClipboardEventArgs> CellCopyEnded { get; set; }
    
    
            protected internal sealed override void OnCellCopyStarted(GridCellClipboardEventArgs e)
            {
                CellCopyStarted?.Invoke(this, e);
            }
    
            protected internal sealed override void OnCellCopyEnded(GridCellClipboardEventArgs e)
            {
                CellCopyEnded?.Invoke(this, e);
            }
    
            //
            // Summary:
            //     Copy the current selection to the clipboard.
            public virtual void Copy()
            {
    	    // TODO: Trigger Event "CellCopyStarted" here
    	    OnCellCopyStarted(new GridCellClipboardEventArgs() { ... });
    
                GridCellRange gridCellRange = ((base.SelectionMode == GridSelectionMode.None) ? CursorRange : Selection);
                if (!(gridCellRange == null))
                {
                    string clipString = GetClipString(gridCellRange);
                    ClipboardEx.SetText(base.Js, clipString);
                }
    
    	    // TODO: Trigger Event "CellCopyEnded" here
    	    OnCellCopyEnded(new GridCellClipboardEventArgs() { ... });
            }

    Please let me know,

    • a) if you can add these events (and if yes, when I can expect the new version to be available) or
    • b) if there is a workaround I just did not see.

    Thx and best from Hamburg, Germany

    Ben.

  • Posted 25 October 2023, 3:23 pm EST

    Hello Ben,

    Thank you for showing your interest in our control. For now, the events are not available, but you may override the Cut(), Copy(), Paste() method those gets triggered on Cut, Copy & paste operation.

    Please refer to the attached sample for reference.

    Also, we have added the enhancement request to the concerned team with the internal tracking id C1XAML-35237.

    We are not sure about the release with these new events. But in the meantime, the provided workaround should work for you.

    Hope it helps!

    Regards,

    Manish Gupta

    FlexGrid_Custom_CopyContent_Clipboard_Inherit.zip

  • Posted 25 October 2023, 8:47 pm EST

    Dear Team GrapeCity / Mescius!

    Dear Greg!

    Dear Manish!

    Thank you so much for your quick help on this issue.

    Simply building a custom grid on top of your FlexGrid works like a charm. I’m a little embarrassed that I didn’t think of it myself straight away.

    Below is a small demo implementation that may be helpful for other users.

    Thank you again and all the best from Hamburg, Germany

    Ben.

    using C1.Blazor.Grid;
    using Microsoft.AspNetCore.Components;
    
    namespace FlexGridTestApp.Client.BaseComponents;
    
    public class CustomFlexGrid : FlexGrid
    {
    
        [Parameter] public EventHandler<GridClipboardEventArgs> ClipboardEvent { get; set; }
    
        [Parameter] public EventHandler<GridClipboardEventArgs> ClipboardCopyStarted { get; set; }
        [Parameter] public EventHandler<GridClipboardEventArgs> ClipboardCopyEnded { get; set; }
    
        [Parameter] public EventHandler<GridClipboardEventArgs> ClipboardCutStarted { get; set; }
        [Parameter] public EventHandler<GridClipboardEventArgs> ClipboardCutEnded { get; set; }
    
        [Parameter] public EventHandler<GridClipboardEventArgs> ClipboardPasteStarted { get; set; }
        [Parameter] public EventHandler<GridClipboardEventArgs> ClipboardPasteEnded { get; set; }
    
    
    
        protected internal GridClipboardEventArgs OnClipboardCopyStarted()
        {
    
            GridClipboardEventArgs e = new GridClipboardEventArgs()
            {
                Cancel = false,
                ClipboardEventType = ClipboardEventType.CopyStarted,
                GridCellRange = ((SelectionMode == GridSelectionMode.None) ? CursorRange : Selection),
            };
            ClipboardEvent?.Invoke(this, e);
            ClipboardCopyStarted?.Invoke(this, e);
            return e;
        }
    
        protected internal GridClipboardEventArgs OnClipboardCopyEnded()
        {
    
            GridClipboardEventArgs e = new GridClipboardEventArgs()
            {
                ClipboardEventType = ClipboardEventType.CopyEnded,
                GridCellRange = ((SelectionMode == GridSelectionMode.None) ? CursorRange : Selection)
            };
            ClipboardEvent?.Invoke(this, e);
            ClipboardCopyEnded?.Invoke(this, e);
            return e;
        }
    
        protected internal GridClipboardEventArgs OnClipboardCutStarted()
        {
    
            GridClipboardEventArgs e = new GridClipboardEventArgs()
            {
                Cancel = false,
                ClipboardEventType = ClipboardEventType.CutStarted,
                GridCellRange = ((SelectionMode == GridSelectionMode.None) ? CursorRange : Selection)
            };
            ClipboardEvent?.Invoke(this, e);
            ClipboardCutStarted?.Invoke(this, e);
            return e;
        }
    
        protected internal GridClipboardEventArgs OnClipboardCutEnded()
        {
    
            GridClipboardEventArgs e = new GridClipboardEventArgs()
            {
                ClipboardEventType = ClipboardEventType.CutEnded,
                GridCellRange = ((SelectionMode == GridSelectionMode.None) ? CursorRange : Selection)
            };
            ClipboardEvent?.Invoke(this, e);
            ClipboardCutEnded?.Invoke(this, e);
            return e;
        }
    
        protected internal GridClipboardEventArgs OnClipboardPasteStarted()
        {
    
            GridClipboardEventArgs e = new GridClipboardEventArgs()
            {
                Cancel = false,
                ClipboardEventType = ClipboardEventType.PasteStarted,
                GridCellRange = ((SelectionMode == GridSelectionMode.None) ? CursorRange : Selection)
            };
            ClipboardEvent?.Invoke(this, e);
            ClipboardPasteStarted?.Invoke(this, e);
            return e;
        }
    
        protected internal GridClipboardEventArgs OnClipboardPasteEnded()
        {
    
            GridClipboardEventArgs e = new GridClipboardEventArgs()
            {
                ClipboardEventType = ClipboardEventType.PasteEnded,
                GridCellRange = ((SelectionMode == GridSelectionMode.None) ? CursorRange : Selection)
            };
            ClipboardEvent?.Invoke(this, e);
            ClipboardPasteEnded?.Invoke(this, e);
            return e;
        }
    
        public override void Copy()
        {
            // Raise event: "Copy Started"
            var startArgs = OnClipboardCopyStarted();
    
            // Check if copy is to be cancelled
            if (startArgs.Cancel)
                return;
    
            // Call base copy implementation
            base.Copy();
    
            // Raise event: "Copy Ended"
            OnClipboardCopyEnded();
        }
    
        public override void Cut()
        {
            // Raise event: "Cut Started"
            var startArgs = OnClipboardCutStarted();
    
            // Check if cut is to be cancelled
            if (startArgs.Cancel)
                return;
    
            // Call base cut implementation
            base.Cut();
    
            // Raise event: "Cut Ended"
            OnClipboardCutEnded();
        }
    
        public override void Paste()
        {
            // Raise event: "Paste Started"
            var startArgs = OnClipboardPasteStarted();
    
            // Check if paste is to be cancelled
            if (startArgs.Cancel)
                return;
    
            // Call base paste implementation
            base.Paste();
    
            // Raise event: "Paste Ended"
            OnClipboardPasteEnded();
        }
    
    }
    
    public class GridClipboardEventArgs
    {
        public bool Cancel { get; set; } = false;
        public GridCellRange GridCellRange { get; set; }
        public ClipboardEventType ClipboardEventType { get; set; }
    
    }
    
    
    public enum ClipboardEventType
    {
        CopyStarted,
        CopyEnded,
        CutStarted,
        CutEnded,
        PasteStarted,
        PasteEnded,
    }
  • Posted 26 October 2023, 2:31 pm EST

    Hello Ben,

    Thank you for letting us know that your issue has been resolved with the provided solution. We are glad to help you.

    As the requirement can be fulfilled using the Cut(), Copy() and Paste() event, so the development team mark this query as done because this is the rare case that user needs events for Clipboard operation.

    Regards,

    Manish Gupta

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels