# Drag and Drop

> Set AllowDrag and AllowDrop in XAML, open files dropped from File Explorer and insert dropped images at the drop point in the WPF DragEnter and Drop handlers.

- **Product:** TX Text Control .NET for WPF
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for WPF > Document Editor > Editing Text > Drag and Drop
- **4127 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/editing-text/drag-drop/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/editing-text/drag-drop/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/editing-text/drag-drop/llms-full.txt

---

With the mouse, users of the WPF `TextControl` move selected text to another place, drag text between the editor and other applications, and drop files onto the document. The first two need at most a property or two; dropped files are handled by your code, which checks the file in `DragEnter` and loads it in `Drop`.

The examples use a window with a `TextControl` named `textControl1`, as in [Create Your First WPF Application](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/document-editor/first-application/llms-full.txt).

### Move and Copy Text With the Mouse

| Mouse action | Result |
|---|---|
| Drag the selected text and drop it | Moves the text to the drop position |
| Hold down Ctrl while dropping the selected text | Copies the text to the drop position |

Both belong to the built-in mouse interface of the editor. The other mouse actions are listed on [Selections and Caret Position](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/editing-text/selections/llms-full.txt).

### Allow Dragging and Dropping

| Property | Controls |
|---|---|
| [AllowDrag](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/allowdrag-property/llms-full.txt) | Whether the editor can be the source of a drag operation, for example to drag selected text into another application |
| [AllowDrop](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/allowdrop-property/llms-full.txt) | Whether the editor accepts data dragged onto it; the property is inherited from `UIElement` |
| [DropFormats](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/dropformats-property/llms-full.txt) | Which formats the editor accepts on its own: `PlainText`, `RichTextFormat`, `HTMLFormat` and `Image` |

`AllowDrag` and `AllowDrop` are set as attributes in XAML, as in the example below. `DropFormats` takes a combination of `DropFormat` values; the following line accepts text with and without formatting, but no HTML or images:

```csharp
textControl1.DropFormats = DropFormat.PlainText | DropFormat.RichTextFormat;
```

`DropFormat.Image` covers device-dependent and device-independent bitmaps, TIFF images and Windows metafiles.

### Accept Files From File Explorer

Files dragged from File Explorer arrive as a list of paths, which your code interprets with the WPF routed events `DragEnter` and `Drop` of the control. In *MainWindow.xaml*, switch dragging and dropping on and connect both events:

```xml
<Window x:Class="SampleApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:WPF="clr-namespace:TXTextControl.WPF;assembly=TXTextControl.WPF"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <WPF:TextControl x:Name="textControl1"
                        AllowDrag="True"
                        AllowDrop="True"
                        DragEnter="TextControl1_DragEnter"
                        Drop="TextControl1_Drop" />
    </Grid>
</Window>
```

The handlers in *MainWindow.xaml.cs* accept a single Word, RTF, HTML, text, TX Text Control, PDF, XML or Excel file and open it as the document. Replace `SampleApp` with the namespace of your project:

```csharp
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using TXTextControl;

namespace SampleApp;

public partial class MainWindow : Window
{
    // The file types this window accepts and their formats
    private static readonly Dictionary<string, StreamType> documentFormats =
        new Dictionary<string, StreamType>(StringComparer.OrdinalIgnoreCase)
        {
            [".docx"] = StreamType.WordprocessingML,
            [".doc"] = StreamType.MSWord,
            [".rtf"] = StreamType.RichTextFormat,
            [".htm"] = StreamType.HTMLFormat,
            [".html"] = StreamType.HTMLFormat,
            [".txt"] = StreamType.PlainText,
            [".tx"] = StreamType.InternalUnicodeFormat,
            [".pdf"] = StreamType.AdobePDF,
            [".xml"] = StreamType.XMLFormat,
            [".xlsx"] = StreamType.SpreadsheetML
        };

    public MainWindow()
    {
        InitializeComponent();
    }

    private static string GetDocumentFile(IDataObject data)
    {
        // A file dragged from File Explorer arrives as an array of paths
        string[] files = data.GetData(DataFormats.FileDrop) as string[];

        if (files == null || files.Length != 1)
        {
            return null;
        }

        return documentFormats.ContainsKey(Path.GetExtension(files[0])) ? files[0] : null;
    }

    private void TextControl1_DragEnter(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(DataFormats.FileDrop))
        {
            e.Effects = GetDocumentFile(e.Data) != null ? DragDropEffects.Copy : DragDropEffects.None;
        }
    }

    private void TextControl1_Drop(object sender, DragEventArgs e)
    {
        string path = GetDocumentFile(e.Data);

        if (path == null)
        {
            return;
        }

        // Replace the document with the dropped file
        textControl1.Load(path, documentFormats[Path.GetExtension(path)]);
    }
}
```

Run the application and drag a DOCX file from File Explorer onto the editor: the file replaces the current document.

The code works as follows:

- `documentFormats` maps file extensions to values of [StreamType](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/streamtype/enumeration/llms-full.txt), the formats the editor loads. A PDF file is imported as described in [PDF Import and Its Limitations](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/pdf/import/llms-full.txt), an XLSX file shows its first worksheet, and an XML file is loaded with the DTD and the stylesheet it refers to, as [XML Processing](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/xml/llms-full.txt) explains.
- `GetDocumentFile` reads the paths with `DataFormats.FileDrop` of the `System.Windows` namespace and returns a single file with a known extension, or `null`.
- In `DragEnter`, `e.Effects` tells WPF whether the file is accepted. Other data is left to the editor, which handles the formats of `DropFormats` itself.
- [Load](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/load-method/llms-full.txt) replaces the content of the editor with the file.

To insert the file into the current document instead of replacing it, call [Selection.Load](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/selection/load-method/llms-full.txt), which puts the content at the input position:

```csharp
textControl1.Selection.Load(path, documentFormats[System.IO.Path.GetExtension(path)]);
```

### Insert Dropped Images at the Drop Point

An image file dropped from File Explorer is best inserted where the mouse was released, not loaded as a document. Add a second map for the image extensions, with the import filter index of each format, and extend the handlers:

```csharp
// The image file types and their import filter indexes
private static readonly Dictionary<string, int> imageFormats =
    new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
    {
        [".bmp"] = 1,
        [".tif"] = 2,
        [".tiff"] = 2,
        [".wmf"] = 3,
        [".png"] = 4,
        [".jpg"] = 5,
        [".jpeg"] = 5,
        [".gif"] = 6,
        [".emf"] = 7,
        [".svg"] = 8
    };

private void InsertDroppedImage(string path, Point dropPoint)
{
    // WPF measures in device-independent units, TX Text Control in pixels
    Matrix toDevice = PresentationSource.FromVisual(textControl1).CompositionTarget.TransformToDevice;
    System.Drawing.Point location = new System.Drawing.Point(
        (int)(dropPoint.X * toDevice.M11), (int)(dropPoint.Y * toDevice.M22));

    // Move the input position to the drop point and insert the image inline there
    textControl1.InputPosition = new InputPosition(location);
    textControl1.Images.Add(new TXTextControl.Image(path, imageFormats[Path.GetExtension(path)]), -1);
}
```

In `GetDocumentFile`, accept a file whose extension is in either map:

```csharp
string extension = Path.GetExtension(files[0]);
return documentFormats.ContainsKey(extension) || imageFormats.ContainsKey(extension) ? files[0] : null;
```

In `TextControl1_Drop`, right after the check for `null`, insert an image instead of loading it:

```csharp
if (imageFormats.ContainsKey(Path.GetExtension(path)))
{
    InsertDroppedImage(path, e.GetPosition(textControl1));
    return;
}
```

The code works as follows:

- `e.GetPosition(textControl1)` returns the drop point relative to the top-left corner of the control, in the device-independent units of WPF. `Point` and `Matrix` are the WPF types of `System.Windows` and `System.Windows.Media`; add `using System.Windows.Media;`.
- The [InputPosition constructor](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/inputposition/constructor/llms-full.txt) with a `System.Drawing.Point` expects pixels from the top-left corner of the control, so the point is scaled with the display's transformation first.
- The [Image constructor](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/image/constructor/llms-full.txt) takes the file and its import filter index, and [ImageCollection.Add](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/imagecollection/add-method/llms-full.txt) with `-1` inserts the image inline at the input position. WPF has an `Image` class of its own, so the code writes `TXTextControl.Image`.

The setup installs a TX Words sample that handles documents and images this way, in *%USERPROFILE%\\Documents\\TX Text Control 34.0.NET for WPF\\CSharp\\TX Words\\Drag And Drop*. Anchoring, sizing and saving images are covered on [Images](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/images/llms-full.txt).

### Next Steps

- [Loading and Saving Documents](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/load-save/llms-full.txt): the formats and options of `Load`.
- [Clipboard Operations](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/editing-text/clipboard/llms-full.txt): copy and paste instead of dragging.
- [Events](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/events/llms-full.txt): the other events of the editor.

---

## Nearby

- **Previous:** [Search and Replace](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/editing-text/search-replace/llms-full.txt)
- **Next:** [Keyboard Shortcuts](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/editing-text/keyboard-shortcuts/llms-full.txt)
