ClientClipboard
ClientClipboard gives server code access to the clipboard of the user's machine, through the browser's Clipboard API. With it you can:
- write text or images to the clipboard, for Copy to clipboard buttons;
- read text or images from it, for Paste buttons, or to import an image copied from another program;
- get an event when the user cuts, copies or pastes anywhere in the application.
System.Windows.Forms.Clipboard and friends work on the server's clipboard, which is no use in a web application. Use this extension whenever you mean the user's clipboard.
Installation
Add the Wisej-4-ClientClipboard package to your Wisej.NET project:
dotnet add package Wisej-4-ClientClipboard
The package targets .NET Framework 4.8 and .NET 8 or later. There's nothing to drop on a page: ClientClipboard is a static class that you call directly.
- The Clipboard API is available only in a secure context: HTTPS, or
http://localhostduring development. - Browsers protect the clipboard. Reading asks the user for permission (
clipboard-read) or shows a Paste prompt, and the call fails if the user refuses. Writing normally works only in response to a user action, such as a button click. - Support differs between browsers, especially for images and for reading. Check the browser compatibility table for the browsers you support.
Getting started
A Copy and a Paste button for a text box:
- C#
- VB.NET
using Wisej.Ext.ClientClipboard;
private async void buttonCopy_Click(object sender, EventArgs e)
{
await ClientClipboard.WriteTextAsync(this.textBox1.Text);
AlertBox.Show("Copied to the clipboard.");
}
private async void buttonPaste_Click(object sender, EventArgs e)
{
try
{
this.textBox1.Text = await ClientClipboard.ReadTextAsync();
}
catch (Exception)
{
AlertBox.Show("Clipboard access was denied.", MessageBoxIcon.Warning);
}
}
Imports Wisej.Ext.ClientClipboard
Private Async Sub ButtonCopy_Click(sender As Object, e As EventArgs) Handles ButtonCopy.Click
Await ClientClipboard.WriteTextAsync(Me.TextBox1.Text)
AlertBox.Show("Copied to the clipboard.")
End Sub
Private Async Sub ButtonPaste_Click(sender As Object, e As EventArgs) Handles ButtonPaste.Click
Try
Me.TextBox1.Text = Await ClientClipboard.ReadTextAsync()
Catch ex As Exception
AlertBox.Show("Clipboard access was denied.", MessageBoxIcon.Warning)
End Try
End Sub
Text
| Method | What it does |
|---|---|
WriteTextAsync(text) | Writes text. The task completes once the browser has updated the clipboard. |
WriteText(text) | Writes text, fire-and-forget. |
WriteText(text, callback) | Writes text and calls callback once the clipboard is updated. |
ReadTextAsync() | Returns the clipboard text, or an empty string when the clipboard is empty or holds no text. |
ReadText(callback) | The same, but delivers the text to callback. |
Images
Images travel as System.Drawing.Image objects, so they go straight into a PictureBox or into your own image processing:
- C#
- VB.NET
// Paste an image copied from another program.
private async void buttonPasteImage_Click(object sender, EventArgs e)
{
var image = await ClientClipboard.ReadImageAsync();
if (image != null)
this.pictureBox1.Image = image;
else
AlertBox.Show("There's no image on the clipboard.");
}
// Copy the image in the PictureBox, as PNG.
private async void buttonCopyImage_Click(object sender, EventArgs e)
{
await ClientClipboard.WriteImageAsync(this.pictureBox1.Image);
}
' Paste an image copied from another program.
Private Async Sub ButtonPasteImage_Click(sender As Object, e As EventArgs) Handles ButtonPasteImage.Click
Dim image = Await ClientClipboard.ReadImageAsync()
If image IsNot Nothing Then
Me.PictureBox1.Image = image
Else
AlertBox.Show("There's no image on the clipboard.")
End If
End Sub
' Copy the image in the PictureBox, as PNG.
Private Async Sub ButtonCopyImage_Click(sender As Object, e As EventArgs) Handles ButtonCopyImage.Click
Await ClientClipboard.WriteImageAsync(Me.PictureBox1.Image)
End Sub
| Method | What it does |
|---|---|
ReadImageAsync() / ReadImage(callback) | Returns the PNG image on the clipboard, or null when there isn't one. |
WriteImageAsync(image) | Writes image as PNG. |
WriteImageAsync(image, format) | Writes image encoded in format. |
WriteImage(image, callback) | Writes image and calls the optional callback once the clipboard is updated. |
Browsers reliably support only image/png on the clipboard. Keep the default PNG unless you know the target browsers accept the format you pick.
The ClipboardChange event
ClipboardChange fires on the server when the user cuts, copies or pastes in the browser with the keyboard or the browser menu. Its ClientClipboardEventArgs tell you what happened:
| Property | What it holds |
|---|---|
Type | Cut, Copy or Paste. |
Target | The control that had the focus, or null. It's also passed as sender. |
Content | The pasted text. The browser provides it only for Paste. |
- C#
- VB.NET
public Page1()
{
InitializeComponent();
ClientClipboard.ClipboardChange += ClientClipboard_ClipboardChange;
this.Disposed += (s, e) => ClientClipboard.ClipboardChange -= ClientClipboard_ClipboardChange;
}
private void ClientClipboard_ClipboardChange(object sender, ClientClipboardEventArgs e)
{
// Only react to clipboard actions on this page's controls.
if (e.Target == null || e.Target.TopLevelControl != this)
return;
if (e.Type == ClientClipboardChangeType.Paste)
this.labelStatus.Text = $"Pasted {e.Content?.Length ?? 0} characters into {e.Target.Name}.";
}
Public Sub New()
InitializeComponent()
AddHandler ClientClipboard.ClipboardChange, AddressOf ClientClipboard_ClipboardChange
AddHandler Me.Disposed, Sub(s, e) RemoveHandler ClientClipboard.ClipboardChange, AddressOf ClientClipboard_ClipboardChange
End Sub
Private Sub ClientClipboard_ClipboardChange(sender As Object, e As ClientClipboardEventArgs)
' Only react to clipboard actions on this page's controls.
If e.Target Is Nothing OrElse e.Target.TopLevelControl IsNot Me Then Return
If e.Type = ClientClipboardChangeType.Paste Then
Me.LabelStatus.Text = $"Pasted {If(e.Content?.Length, 0)} characters into {e.Target.Name}."
End If
End Sub
ClipboardChange is a static event, so it's shared by every session in the application process, not just the current user's. Each handler you attach receives clipboard actions from all users, so:
- always detach the handler when its page or form is disposed, as above. Otherwise the handlers of closed pages pile up and keep those objects alive;
- in the handler, ignore events whose
Targetdoesn't belong to the object that attached it.