|
| 1 | +--- |
| 2 | +description: Learn how to implement copy and paste functionality in WinUI and UWP apps using the clipboard APIs. Includes code examples and best practices. |
| 3 | +title: Copy and Paste in WinUI and UWP Apps |
| 4 | +ms.date: 10/15/2025 |
| 5 | +ms.topic: how-to |
| 6 | +keywords: windows 11, uwp, winrt, windows runtime, winui |
| 7 | +ms.localizationpriority: medium |
| 8 | +# Customer intent: As a Windows app developer, I want to learn how to implement copy and paste functionality in my app using the clipboard. |
| 9 | +--- |
| 10 | + |
| 11 | +# Copy and paste |
| 12 | + |
| 13 | +Copy and paste is a fundamental way for users to exchange data between apps or within an app. This article shows you how to implement copy and paste in WinUI and Universal Windows Platform (UWP) apps using the clipboard APIs. You'll learn how to copy, cut, and paste data, track clipboard changes, and use the [DataPackage](/uwp/api/Windows.ApplicationModel.DataTransfer.DataPackage) class to handle different data formats. |
| 14 | + |
| 15 | +> [!NOTE] |
| 16 | +> You can also use these APIs in other desktop apps through Windows Runtime (WinRT) APIs. For more information, see [Call Windows Runtime APIs in desktop apps](/windows/apps/desktop/modernize/desktop-to-uwp-enhance). |
| 17 | +
|
| 18 | +For complete code examples that demonstrate different copy and paste scenarios, see the [UWP clipboard sample on GitHub](https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/Clipboard). |
| 19 | + |
| 20 | +## Check for built-in clipboard support |
| 21 | + |
| 22 | +In many cases, you do not need to write code to support clipboard operations. Many of the default XAML controls you can use to create apps already support clipboard operations. |
| 23 | + |
| 24 | +## Get set up |
| 25 | + |
| 26 | +First, include the [Windows.ApplicationModel.DataTransfer](/uwp/api/Windows.ApplicationModel.DataTransfer) namespace in your app. Then, add an instance of the [DataPackage](/uwp/api/Windows.ApplicationModel.DataTransfer.DataPackage) object. This object contains both the data the user wants to copy and any properties (such as a description) that you want to include. |
| 27 | + |
| 28 | +### [C#](#tab/cs) |
| 29 | + |
| 30 | +```cs |
| 31 | +using Windows.ApplicationModel.DataTransfer; |
| 32 | +... |
| 33 | +var dataPackage = new DataPackage(); |
| 34 | +``` |
| 35 | + |
| 36 | +### [C++/WinRT](#tab/cppwinrt) |
| 37 | + |
| 38 | +```cppwinrt |
| 39 | +#include <winrt/Windows.ApplicationModel.DataTransfer.h> |
| 40 | +using namespace winrt::Windows::ApplicationModel::DataTransfer; |
| 41 | +... |
| 42 | +DataPackage dataPackage; |
| 43 | +``` |
| 44 | + |
| 45 | +--- |
| 46 | + |
| 47 | +## Copy and cut |
| 48 | + |
| 49 | +Copy and cut (also referred to as *move*) work almost exactly the same. Choose which operation you want by using the [RequestedOperation](/uwp/api/windows.applicationmodel.datatransfer.datapackage.requestedoperation) property. |
| 50 | + |
| 51 | +### [C#](#tab/cs) |
| 52 | + |
| 53 | +```cs |
| 54 | +// copy |
| 55 | +dataPackage.RequestedOperation = DataPackageOperation.Copy; |
| 56 | +// or cut |
| 57 | +dataPackage.RequestedOperation = DataPackageOperation.Move; |
| 58 | +``` |
| 59 | + |
| 60 | +### [C++/WinRT](#tab/cppwinrt) |
| 61 | + |
| 62 | +```cppwinrt |
| 63 | +// copy |
| 64 | +dataPackage.RequestedOperation(DataPackageOperation::Copy); |
| 65 | +// or cut |
| 66 | +dataPackage.RequestedOperation(DataPackageOperation::Move); |
| 67 | +``` |
| 68 | + |
| 69 | +--- |
| 70 | + |
| 71 | +## Set the copied content |
| 72 | + |
| 73 | +Next, you can add the data that a user has selected to the [DataPackage](/uwp/api/Windows.ApplicationModel.DataTransfer.DataPackage) object. If this data is supported by the **DataPackage** class, you can use one of the corresponding [methods](/uwp/api/windows.applicationmodel.datatransfer.datapackage#methods) of the **DataPackage** object. Here's how to add text by using the [SetText](/uwp/api/windows.applicationmodel.datatransfer.datapackage.settext) method: |
| 74 | + |
| 75 | +### [C#](#tab/cs) |
| 76 | + |
| 77 | +```cs |
| 78 | +dataPackage.SetText("Hello World!"); |
| 79 | +``` |
| 80 | + |
| 81 | +### [C++/WinRT](#tab/cppwinrt) |
| 82 | + |
| 83 | +```cppwinrt |
| 84 | +dataPackage.SetText(L"Hello World!"); |
| 85 | +``` |
| 86 | + |
| 87 | +--- |
| 88 | + |
| 89 | +The last step is to add the [DataPackage](/uwp/api/Windows.ApplicationModel.DataTransfer.DataPackage) to the clipboard by calling the static [SetContent](/uwp/api/windows.applicationmodel.datatransfer.clipboard.setcontent) method. |
| 90 | + |
| 91 | +### [C#](#tab/cs) |
| 92 | + |
| 93 | +```cs |
| 94 | +Clipboard.SetContent(dataPackage); |
| 95 | +``` |
| 96 | + |
| 97 | +### [C++/WinRT](#tab/cppwinrt) |
| 98 | + |
| 99 | +```cppwinrt |
| 100 | +Clipboard::SetContent(dataPackage); |
| 101 | +``` |
| 102 | + |
| 103 | +--- |
| 104 | + |
| 105 | +## Paste |
| 106 | + |
| 107 | +To get the contents of the clipboard, call the static [GetContent](/uwp/api/windows.applicationmodel.datatransfer.clipboard.getcontent) method. This method returns a [DataPackageView](/uwp/api/Windows.ApplicationModel.DataTransfer.DataPackageView) that contains the content. This object is almost identical to a [DataPackage](/uwp/api/Windows.ApplicationModel.DataTransfer.DataPackage) object, except that its contents are read-only. With that object, you can use either the [AvailableFormats](/uwp/api/windows.applicationmodel.datatransfer.datapackageview.availableformats) or the [Contains](/uwp/api/windows.applicationmodel.datatransfer.datapackageview.contains) method to identify what formats are available. Then, you can call the corresponding [DataPackageView](/uwp/api/Windows.ApplicationModel.DataTransfer.DataPackageView) method to get the data. |
| 108 | + |
| 109 | +### [C#](#tab/cs) |
| 110 | + |
| 111 | +```cs |
| 112 | +async void OutputClipboardText() |
| 113 | +{ |
| 114 | + DataPackageView dataPackageView = Clipboard.GetContent(); |
| 115 | + if (dataPackageView.Contains(StandardDataFormats.Text)) |
| 116 | + { |
| 117 | + string text = await dataPackageView.GetTextAsync(); |
| 118 | + // To output the text from this example, you need a TextBlock control |
| 119 | + TextOutput.Text = "Clipboard now contains: " + text; |
| 120 | + } |
| 121 | +} |
| 122 | +``` |
| 123 | + |
| 124 | +### [C++/WinRT](#tab/cppwinrt) |
| 125 | + |
| 126 | +```cppwinrt |
| 127 | +void MainPage::OutputClipboardText() |
| 128 | +{ |
| 129 | + DataPackageView dataPackageView = Clipboard::GetContent(); |
| 130 | + if (dataPackageView.Contains(StandardDataFormats::Text())) |
| 131 | + { |
| 132 | + hstring text = dataPackageView.GetTextAsync().get(); |
| 133 | + // To output the text from this example, you need a TextBlock control |
| 134 | + TextOutput().Text(L"Clipboard now contains: " + text); |
| 135 | + } |
| 136 | +} |
| 137 | +``` |
| 138 | + |
| 139 | +--- |
| 140 | + |
| 141 | +## Track changes to the clipboard |
| 142 | + |
| 143 | +In addition to copy and paste commands, you may also want to track clipboard changes. Do this by handling the clipboard's [ContentChanged](/uwp/api/windows.applicationmodel.datatransfer.clipboard.contentchanged) event. |
| 144 | + |
| 145 | +### [C#](#tab/cs) |
| 146 | + |
| 147 | +```cs |
| 148 | +Clipboard.ContentChanged += async (s, e) => |
| 149 | +{ |
| 150 | + DataPackageView dataPackageView = Clipboard.GetContent(); |
| 151 | + if (dataPackageView.Contains(StandardDataFormats.Text)) |
| 152 | + { |
| 153 | + string text = await dataPackageView.GetTextAsync(); |
| 154 | + // To output the text from this example, you need a TextBlock control |
| 155 | + TextOutput.Text = "Clipboard now contains: " + text; |
| 156 | + } |
| 157 | +} |
| 158 | +``` |
| 159 | +### [C++/WinRT](#tab/cppwinrt) |
| 160 | + |
| 161 | +```cppwinrt |
| 162 | +Clipboard::ContentChanged([this](auto const&, auto const&) |
| 163 | +{ |
| 164 | + DataPackageView dataPackageView = Clipboard::GetContent(); |
| 165 | + if (dataPackageView.Contains(StandardDataFormats::Text())) |
| 166 | + { |
| 167 | + hstring text = dataPackageView.GetTextAsync().get(); |
| 168 | + // To output the text from this example, you need a TextBlock control |
| 169 | + TextOutput().Text(L"Clipboard now contains: " + text); |
| 170 | + } |
| 171 | +}); |
| 172 | +``` |
| 173 | + |
| 174 | +--- |
| 175 | + |
| 176 | +## Related content |
| 177 | + |
| 178 | +- [Clipboard sample](https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/Clipboard) |
| 179 | +- [Communication](index.md) |
| 180 | +- [DataTransfer](/uwp/api/windows.applicationmodel.datatransfer) |
| 181 | +- [DataPackage](/uwp/api/windows.applicationmodel.datatransfer.datapackage) |
| 182 | +- [DataPackageView](/uwp/api/windows.applicationmodel.datatransfer.datapackageview) |
| 183 | +- [DataPackagePropertySet]( /uwp/api/Windows.ApplicationModel.DataTransfer.DataPackagePropertySet) |
| 184 | +- [DataRequest](/uwp/api/windows.applicationmodel.datatransfer.datarequest) |
| 185 | +- [DataRequested]( /uwp/api/Windows.ApplicationModel.DataTransfer.DataTransferManager) |
| 186 | +- [FailWithDisplayText](/uwp/api/windows.applicationmodel.datatransfer.datarequest.failwithdisplaytext) |
| 187 | +- [ShowShareUi](/uwp/api/windows.applicationmodel.datatransfer.datatransfermanager.showshareui) |
| 188 | +- [RequestedOperation](/uwp/api/windows.applicationmodel.datatransfer.datapackage.requestedoperation) |
| 189 | +- [ControlsList](/windows/apps/design/controls/index) |
| 190 | +- [SetContent](/uwp/api/windows.applicationmodel.datatransfer.clipboard.setcontent) |
| 191 | +- [GetContent](/uwp/api/windows.applicationmodel.datatransfer.clipboard.getcontent) |
| 192 | +- [AvailableFormats](/uwp/api/windows.applicationmodel.datatransfer.datapackageview.availableformats) |
| 193 | +- [Contains](/uwp/api/windows.applicationmodel.datatransfer.datapackageview.contains) |
| 194 | +- [ContentChanged](/uwp/api/windows.applicationmodel.datatransfer.clipboard.contentchanged) |
0 commit comments