달력

1

« 2025/1 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

고급 - 끌어서 놓기


https://msdn.microsoft.com/ko-kr/library/ms742859(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/ms742859(v=vs.110).aspx




Drag and Drop Overview


This topic provides an overview of drag-and-drop support in Windows Presentation Foundation (WPF) applications. Drag-and-drop commonly refers to a method of data transfer that involves using a mouse (or some other pointing device) to select one or more objects, dragging these objects over some desired drop target in the user interface (UI), and dropping them.

Drag-and-Drop Support in WPF

Drag-and-drop operations typically involve two parties: a drag source from which the dragged object originates and a drop target which receives the dropped object. The drag source and drop target may be UI elements in the same application or a different application.

The type and number of objects that can be manipulated with drag-and-drop is completely arbitrary. For example, files, folders, and selections of content are some of the more common objects manipulated through drag-and-drop operations.

The particular actions performed during a drag-and-drop operation are application specific, and often determined by context. For example, dragging a selection of files from one folder to another on the same storage device moves the files by default, whereas dragging files from a Universal Naming Convention (UNC) share to a local folder copies the files by default.

The drag-and-drop facilities provided by WPF are designed to be highly flexible and customizable to support a wide variety of drag-and-drop scenarios. Drag-and-drop supports manipulating objects within a single application, or between different applications. Dragging-and-dropping between WPF applications and other Windows applications is also fully supported.

In WPF, any UIElement or ContentElement can participate in drag-and-drop. The events and methods required for drag-and-drop operations are defined in the DragDrop class. The UIElement and ContentElement classes contain aliases for the DragDrop attached events so that the events appear in the class members list when a UIElement or ContentElement is inherited as a base element. Event handlers that are attached to these events are attached to the underlying DragDrop attached event and receive the same event data instance. For more information, see the UIElement.Drop event.

System_CAPS_security Security Note

OLE drag-and-drop does not work while in the Internet zone.

Data Transfer

Drag-and-drop is part of the more general area of data transfer. Data transfer includes drag-and-drop and copy-and-paste operations. A drag-and-drop operation is analogous to a copy-and-paste or cut-and-paste operation that is used to transfer data from one object or application to another by using the system clipboard. Both types of operations require:

  • A source object that provides the data.

  • A way to temporarily store the transferred data.

  • A target object that receives the data.

In a copy-and-paste operation, the system clipboard is used to temporarily store the transferred data; in a drag-and-drop operation, a DataObject is used to store the data. Conceptually, a data object consists of one or more pairs of an Object that contains the actual data, and a corresponding data format identifier.

The drag source initiates a drag-and-drop operation by calling the static DragDrop.DoDragDrop method and passing the transferred data to it. The DoDragDrop method will automatically wrap the data in a DataObject if necessary. For greater control over the data format, you can wrap the data in a DataObject before passing it to the DoDragDrop method. The drop target is responsible for extracting the data from the DataObject. For more information about working with data objects, see Data and Data Objects.

The source and target of a drag-and-drop operation are UI elements; however, the data that is actually being transferred typically does not have a visual representation. You can write code to provide a visual representation of the data that is dragged, such as occurs when dragging files in Windows Explorer. By default, feedback is provided to the user by changing the cursor to represent the effect that the drag-and-drop operation will have on the data, such as whether the data will be moved or copied.

Drag-and-Drop Effects

Drag-and-drop operations can have different effects on the transferred data. For example, you can copy the data or you can move the data. WPF defines a DragDropEffects enumeration that you can use to specify the effect of a drag-and-drop operation. In the drag source, you can specify the effects that the source will allow in the DoDragDrop method. In the drop target, you can specify the effect that the target intends in the Effectsproperty of the DragEventArgs class. When the drop target specifies its intended effect in the DragOver event, that information is passed back to the drag source in the GiveFeedback event. The drag source uses this information to inform the user what effect the drop target intends to have on the data. When the data is dropped, the drop target specifies its actual effect in the Drop event. That information is passed back to the drag source as the return value of the DoDragDrop method. If the drop target returns an effect that is not in the drag sources list of allowedEffects, the drag-and-drop operation is cancelled without any data transfer occurring.

It is important to remember that in WPF, the DragDropEffects values are only used to provide communication between the drag source and the drop target regarding the effects of the drag-and-drop operation. The actual effect of the drag-and-drop operation depends on you to write the appropriate code in your application.

For example, the drop target might specify that the effect of dropping data on it is to move the data. However, to move the data, it must be both added to the target element and removed from the source element. The source element might indicate that it allows moving the data, but if you do not provide the code to remove the data from the source element, the end result will be that the data is copied, and not moved.

Drag-and-Drop Events

Drag-and-drop operations support an event driven model. Both the drag source and the drop target use a standard set of events to handle drag-and-drop operations. The following tables summarize the standard drag-and-drop events. These are attached events on the DragDrop class. For more information about attached events, see Attached Events Overview.

Drag Source Events

Event

Summary

GiveFeedback

This event occurs continuously during a drag-and-drop operation, and enables the drop source to give feedback information to the user. This feedback is commonly given by changing the appearance of the mouse pointer to indicate the effects allowed by the drop target. This is a bubbling event.

QueryContinueDrag

This event occurs when there is a change in the keyboard or mouse button states during a drag-and-drop operation, and enables the drop source to cancel the drag-and-drop operation depending on the key/button states. This is a bubbling event.

PreviewGiveFeedback

Tunneling version of GiveFeedback.

PreviewQueryContinueDrag

Tunneling version of QueryContinueDrag.

Drop Target Events

Event

Summary

DragEnter

This event occurs when an object is dragged into the drop target's boundary. This is a bubbling event.

DragLeave

This event occurs when an object is dragged out of the drop target's boundary. This is a bubbling event.

DragOver

This event occurs continuously while an object is dragged (moved) within the drop target's boundary. This is a bubbling event.

Drop

This event occurs when an object is dropped on the drop target. This is a bubbling event.

PreviewDragEnter

Tunneling version of DragEnter.

PreviewDragLeave

Tunneling version of DragLeave.

PreviewDragOver

Tunneling version of DragOver.

PreviewDrop

Tunneling version of Drop.

To handle drag-and-drop events for instances of an object, add handlers for the events listed in the preceding tables. To handle drag-and-drop events at the class level, override the corresponding virtual On*Event and On*PreviewEvent methods. For more information, see Class Handling of Routed Events by Control Base Classes.

Implementing Drag-and-Drop

A UI element can be a drag source, a drop target, or both. To implement basic drag-and-drop, you write code to initiate the drag-and-drop operation and to process the dropped data. You can enhance the drag-and-drop experience by handling optional drag-and-drop events.

To implement basic drag-and-drop, you will complete the following tasks:

  • Identify the element that will be a drag source. A drag source can be a UIElement or a ContentElement.

  • Create an event handler on the drag source that will initiate the drag-and-drop operation. The event is typically the MouseMove event.

  • In the drag source event handler, call the DoDragDrop method to initiate the drag-and-drop operation. In the DoDragDrop call, specify the drag source, the data to be transferred, and the allowed effects.

  • Identify the element that will be a drop target. A drop target can be UIElement or a ContentElement.

  • On the drop target, set the AllowDrop property to true.

  • In the drop target, create a Drop event handler to process the dropped data.

  • In the Drop event handler, extract the data from the DragEventArgs by using the GetDataPresent and GetData methods.

  • In the Drop event handler, use the data to perform the desired drag-and-drop operation.

You can enhance your drag-and-drop implementation by creating a custom DataObject and by handling optional drag source and drop target events, as shown in the following tasks:

  • To transfer custom data or multiple data items, create a DataObject to pass to the DoDragDrop method.

  • To perform additional actions during a drag, handle the DragEnterDragOver, and DragLeave events on the drop target.

  • To change the appearance of the mouse pointer, handle the GiveFeedback event on the drag source.

  • To change how the drag-and-drop operation is canceled, handle the QueryContinueDrag event on the drag source.

Drag-and-Drop Example

This section describes how to implement drag-and-drop for an Ellipse element. The Ellipse is both a drag source and a drop target. The transferred data is the string representation of the ellipse’s Fill property. The following XAML shows the Ellipse element and the drag-and-drop related events that it handles. For complete steps on how to implement drag-and-drop, see Walkthrough: Enabling Drag and Drop on a User Control.

<Ellipse Height="50" Width="50" Fill="Green"
     MouseMove="ellipse_MouseMove"
     GiveFeedback="ellipse_GiveFeedback"
     AllowDrop="True"
     DragEnter="ellipse_DragEnter" DragLeave="ellipse_DragLeave"
     DragOver="ellipse_DragOver" Drop="ellipse_Drop" />

Enabling an Element to be a Drag Source

An object that is a drag source is responsible for:

  • Identifying when a drag occurs.

  • Initiating the drag-and-drop operation.

  • Identifying the data to be transferred.

  • Specifying the effects that the drag-and-drop operation is allowed to have on the transferred data.

The drag source may also give feedback to the user regarding the allowed actions (move, copy, none), and can cancel the drag-and-drop operation based on additional user input, such as pressing the ESC key during the drag.

It is the responsibility of your application to determine when a drag occurs, and then initiate the drag-and-drop operation by calling the DoDragDrop method. Typically, this is when a MouseMove event occurs over the element to be dragged while a mouse button is pressed. The following example shows how to initiate a drag-and-drop operation from the MouseMove event handler of an Ellipse element to make it a drag source. The transferred data is the string representation of the ellipse’s Fill property.

private void ellipse_MouseMove(object sender, MouseEventArgs e)
{
    Ellipse ellipse = sender as Ellipse;
    if (ellipse != null && e.LeftButton == MouseButtonState.Pressed)
    {
        DragDrop.DoDragDrop( ellipse,
                             ellipse.Fill.ToString(),
                             DragDropEffects.Copy);
    }
}

Inside of the MouseMove event handler, call the DoDragDrop method to initiate the drag-and-drop operation. The DoDragDrop method takes three parameters:

  • dragSource – A reference to the dependency object that is the source of the transferred data; this is typically the source of the MouseMoveevent.

  • data - An object that contains the transferred data, wrapped in a DataObject.

  • allowedEffects - One of the DragDropEffects enumeration values that specifies the permitted effects of the drag-and-drop operation.

Any serializable object can be passed in the data parameter. If the data is not already wrapped in a DataObject, it will automatically be wrapped in a new DataObject. To pass multiple data items, you must create the DataObject yourself, and pass it to the DoDragDrop method. For more information, see Data and Data Objects.

The allowedEffects parameter is used to specify what the drag source will allow the drop target to do with the transferred data. The common values for a drag source are CopyMove, and All.

System_CAPS_noteNote

The drop target is also able to specify what effects it intends in response to the dropped data. For example, if the drop target does not recognize the data type to be dropped, it can refuse the data by setting its allowed effects to None. It typically does this in its DragOver event handler.

A drag source can optionally handle the GiveFeedback and QueryContinueDrag events. These events have default handlers that are used unless you mark the events as handled. You will typically ignore these events unless you have a specific need to change their default behavior.

The GiveFeedback event is raised continuously while the drag source is being dragged. The default handler for this event checks whether the drag source is over a valid drop target. If it is, it checks the allowed effects of the drop target. It then gives feedback to the end user regarding the allowed drop effects. This is typically done by changing the mouse cursor to a no-drop, copy, or move cursor. You should only handle this event if you need to use custom cursors to provide feedback to the user. If you handle this event, be sure to mark it as handled so that the default handler does not override your handler.

The QueryContinueDrag event is raised continuously while the drag source is being dragged. You can handle this event to determine what action ends the drag-and-drop operation based on the state of the ESC, SHIFT, CTRL, and ALT keys, as well as the state of the mouse buttons. The default handler for this event cancels the drag-and-drop operation if the ESC key is pressed, and drops the data if the mouse button is released.

System_CAPS_cautionCaution

These events are raised continuously during the drag-and-drop operation. Therefore, you should avoid resource-intensive tasks in the event handlers. For example, use a cached cursor instead of creating a new cursor each time the GiveFeedback event is raised.

Enabling an Element to be a Drop Target

An object that is a drop target is responsible for:

  • Specifying that it is a valid drop target.

  • Responding to the drag source when it drags over the target.

  • Checking that the transferred data is in a format that it can receive.

  • Processing the dropped data.

To specify that an element is a drop target, you set its AllowDrop property to true. The drop target events will then be raised on the element so that you can handle them. During a drag-and-drop operation, the following sequence of events occurs on the drop target:

  1. DragEnter

  2. DragOver

  3. DragLeave or Drop

The DragEnter event occurs when the data is dragged into the drop target's boundary. You typically handle this event to provide a preview of the effects of the drag-and-drop operation, if appropriate for your application. Do not set the DragEventArgs.Effects property in the DragEnter event, as it will be overwritten in the DragOver event.

The following example shows the DragEnter event handler for an Ellipse element. This code previews the effects of the drag-and-drop operation by saving the current Fill brush. It then uses the GetDataPresent method to check whether the DataObject being dragged over the ellipse contains string data that can be converted to a Brush. If so, the data is extracted using the GetData method. It is then converted to a Brush and applied to the ellipse. The change is reverted in the DragLeave event handler. If the data cannot be converted to a Brush, no action is performed.

private Brush _previousFill = null;
private void ellipse_DragEnter(object sender, DragEventArgs e)
{
    Ellipse ellipse = sender as Ellipse;
    if (ellipse != null)
    {
        // Save the current Fill brush so that you can revert back to this value in DragLeave.
        _previousFill = ellipse.Fill;

        // If the DataObject contains string data, extract it.
        if (e.Data.GetDataPresent(DataFormats.StringFormat))
        {
            string dataString = (string)e.Data.GetData(DataFormats.StringFormat);

            // If the string can be converted into a Brush, convert it.
            BrushConverter converter = new BrushConverter();
            if (converter.IsValid(dataString))
            {
                Brush newFill = (Brush)converter.ConvertFromString(dataString);
                ellipse.Fill = newFill;
            }
        }
    }
}

The DragOver event occurs continuously while the data is dragged over the drop target. This event is paired with the GiveFeedback event on the drag source. In the DragOver event handler, you typically use the GetDataPresent and GetData methods to check whether the transferred data is in a format that the drop target can process. You can also check whether any modifier keys are pressed, which will typically indicate whether the user intends a move or copy action. After these checks are performed, you set the DragEventArgs.Effects property to notify the drag source what effect dropping the data will have. The drag source receives this information in the GiveFeedback event args, and can set an appropriate cursor to give feedback to the user.

The following example shows the DragOver event handler for an Ellipse element. This code checks to see if the DataObject being dragged over the ellipse contains string data that can be converted to a Brush. If so, it sets the DragEventArgs.Effects property to Copy. This indicates to the drag source that the data can be copied to the ellipse. If the data cannot be converted to a Brush, the DragEventArgs.Effects property is set to None. This indicates to the drag source that the ellipse is not a valid drop target for the data.

private void ellipse_DragOver(object sender, DragEventArgs e)
{
    e.Effects = DragDropEffects.None;

    // If the DataObject contains string data, extract it.
    if (e.Data.GetDataPresent(DataFormats.StringFormat))
    {
        string dataString = (string)e.Data.GetData(DataFormats.StringFormat);

        // If the string can be converted into a Brush, allow copying.
        BrushConverter converter = new BrushConverter();
        if (converter.IsValid(dataString))
        {
            e.Effects = DragDropEffects.Copy | DragDropEffects.Move;
        }
    }
}

The DragLeave event occurs when the data is dragged out of the target's boundary without being dropped. You handle this event to undo anything that you did in the DragEnter event handler.

The following example shows the DragLeave event handler for an Ellipse element. This code undoes the preview performed in the DragEnter event handler by applying the saved Brush to the ellipse.

private void ellipse_DragLeave(object sender, DragEventArgs e)
{
    Ellipse ellipse = sender as Ellipse;
    if (ellipse != null)
    {
        ellipse.Fill = _previousFill;
    }
}

The Drop event occurs when the data is dropped over the drop target; by default, this happens when the mouse button is released. In the Dropevent handler, you use the GetData method to extract the transferred data from the DataObject and perform any data processing that your application requires. The Drop event ends the drag-and-drop operation.

The following example shows the Drop event handler for an Ellipse element. This code applies the effects of the drag-and-drop operation, and is similar to the code in the DragEnter event handler. It checks to see if the DataObject being dragged over the ellipse contains string data that can be converted to a Brush. If so, the Brush is applied to the ellipse. If the data cannot be converted to a Brush, no action is performed.

private void ellipse_Drop(object sender, DragEventArgs e)
{
    Ellipse ellipse = sender as Ellipse;
    if (ellipse != null)
    {
        // If the DataObject contains string data, extract it.
        if (e.Data.GetDataPresent(DataFormats.StringFormat))
        {
            string dataString = (string)e.Data.GetData(DataFormats.StringFormat);

            // If the string can be converted into a Brush, 
            // convert it and apply it to the ellipse.
            BrushConverter converter = new BrushConverter();
            if (converter.IsValid(dataString))
            {
                Brush newFill = (Brush)converter.ConvertFromString(dataString);
                ellipse.Fill = newFill;
            }
        }
    }
}





Data and Data Objects


Data that is transferred as part of a drag-and-drop operation is stored in a data object. Conceptually, a data object consists of one or more of the following pairs:

  • An Object that contains the actual data.

  • A corresponding data format identifier.

The data itself can consist of anything that can be represented as a base Object. The corresponding data format is a string or Type that provides a hint about what format the data is in. Data objects support hosting multiple data/data format pairs; this enables a single data object to provide data in multiple formats.

Data Objects

All data objects must implement the IDataObject interface, which provides the following standard set of methods that enable and facilitate data transfer.

Method

Summary

GetData

Retrieves a data object in a specified data format.

GetDataPresent

Checks to see whether the data is available in, or can be converted to, a specified format.

GetFormats

Returns a list of formats that the data in this data object is stored in, or can be converted to.

SetData

Stores the specified data in this data object.

WPF provides a basic implementation of IDataObject in the DataObject class. The stock DataObject class is sufficient for many common data transfer scenarios.

There are several pre-defined formats, such as bitmap, CSV, file, HTML, RTF, string, text, and audio. For information about pre-defined data formats provided with WPF, see the DataFormats class reference topic.

Data objects commonly include a facility for automatically converting data stored in one format to a different format while extracting data; this facility is referred to as auto-convert. When querying for the data formats available in a data object, auto-convertible data formats can be filtered from native data formats by calling the GetFormats(Boolean) or GetDataPresent(String, Boolean) method and specifying the autoConvert parameter as false. When adding data to a data object with the SetData(String, Object, Boolean) method, auto-conversion of data can be prohibited by setting the autoConvert parameter to false.

Working with Data Objects

This section describes common techniques for creating and working with data objects.

Creating New Data Objects

The DataObject class provides several overloaded constructors that facilitate populating a new DataObject instance with a single data/data format pair.

The following example code creates a new data object and uses one of the overloaded constructors DataObject(DataObject(String, Object)) to initialize the data object with a string and a specified data format. In this case, the data format is specified by a string; the DataFormats class provides a set of pre-defined type strings. Auto-conversion of the stored data is allowed by default.

string stringData = "Some string data to store...";
string dataFormat = DataFormats.UnicodeText;
DataObject dataObject = new DataObject(dataFormat, stringData);

For more examples of code that creates a data object, see How to: Create a Data Object.

Storing Data in Multiple Formats

A single data object is able to store data in multiple formats. Strategic use of multiple data formats within a single data object potentially makes the data object consumable by a wider variety of drop targets than if only a single data format could be represented. Note that, in general, a drag source must be agnostic about the data formats that are consumable by potential drop targets.

The following example shows how to use the SetData(String, Object) method to add data to a data object in multiple formats.

DataObject dataObject = new DataObject();
string sourceData = "Some string data to store...";

// Encode the source string into Unicode byte arrays.
byte[] unicodeText = Encoding.Unicode.GetBytes(sourceData); // UTF-16
byte[] utf8Text = Encoding.UTF8.GetBytes(sourceData);
byte[] utf32Text = Encoding.UTF32.GetBytes(sourceData);

// The DataFormats class does not provide data format fields for denoting
// UTF-32 and UTF-8, which are seldom used in practice; the following strings 
// will be used to identify these "custom" data formats.
string utf32DataFormat = "UTF-32";
string utf8DataFormat  = "UTF-8";

// Store the text in the data object, letting the data object choose
// the data format (which will be DataFormats.Text in this case).
dataObject.SetData(sourceData);
// Store the Unicode text in the data object.  Text data can be automatically
// converted to Unicode (UTF-16 / UCS-2) format on extraction from the data object; 
// Therefore, explicitly converting the source text to Unicode is generally unnecessary, and
// is done here as an exercise only.
dataObject.SetData(DataFormats.UnicodeText, unicodeText);
// Store the UTF-8 text in the data object...
dataObject.SetData(utf8DataFormat, utf8Text);
// Store the UTF-32 text in the data object...
dataObject.SetData(utf32DataFormat, utf32Text);

Querying a Data Object for Available Formats

Because a single data object can contain an arbitrary number of data formats, data objects include facilities for retrieving a list of available data formats.

The following example code uses the GetFormats overload to get an array of strings denoting all data formats available in a data object (both native and by auto-convert).

DataObject dataObject = new DataObject("Some string data to store...");

// Get an array of strings, each string denoting a data format
// that is available in the data object.  This overload of GetDataFormats
// returns all available data formats, native and auto-convertible.
string[] dataFormats = dataObject.GetFormats();

// Get the number of data formats present in the data object, including both
// auto-convertible and native data formats.
int numberOfDataFormats = dataFormats.Length;

// To enumerate the resulting array of data formats, and take some action when
// a particular data format is found, use a code structure similar to the following.
foreach (string dataFormat in dataFormats)
{
    if (dataFormat == DataFormats.Text)
    {
        // Take some action if/when data in the Text data format is found.
        break;
    }
    else if(dataFormat == DataFormats.StringFormat)
    {
        // Take some action if/when data in the string data format is found.
        break;
    }
}

For more examples of code that queries a data object for available data formats, see How to: List the Data Formats in a Data Object. For examples of querying a data object for the presence of a particular data format, see How to: Determine if a Data Format is Present in a Data Object.

Retrieving Data from a Data Object

Retrieving data from a data object in a particular format simply involves calling one of the GetData methods and specifying the desired data format. One of the GetDataPresent methods can be used to check for the presence of a particular data format. GetData returns the data in an Object; depending on the data format, this object can be cast to a type-specific container.

The following example code uses the GetDataPresent(String) overload to check if a specified data format is available (native or by auto-convert). If the specified format is available, the example retrieves the data by using the GetData(String) method.

DataObject dataObject = new DataObject("Some string data to store...");

string desiredFormat = DataFormats.UnicodeText;
byte[] data = null;

// Use the GetDataPresent method to check for the presence of a desired data format.
// This particular overload of GetDataPresent looks for both native and auto-convertible 
// data formats.
if (dataObject.GetDataPresent(desiredFormat))
{
    // If the desired data format is present, use one of the GetData methods to retrieve the
    // data from the data object.
    data = dataObject.GetData(desiredFormat) as byte[];
}

For more examples of code that retrieves data from a data object, see How to: Retrieve Data in a Particular Data Format.

Removing Data From a Data Object

Data cannot be directly removed from a data object. To effectively remove data from a data object, follow these steps:

  1. Create a new data object that will contain only the data you want to retain.

  2. "Copy" the desired data from the old data object to the new data object. To copy the data, use one of the GetData methods to retrieve an Object that contains the raw data, and then use one of the SetData methods to add the data to the new data object.

  3. Replace the old data object with the new one.

System_CAPS_noteNote

The SetData methods only add data to a data object; they do not replace data, even if the data and data format are exactly the same as a previous call. Calling SetData twice for the same data and data format will result in the data/data format being present twice in the data object.





Walkthrough: Enabling Drag and Drop on a User Control


This walkthrough demonstrates how to create a custom user control that can participate in drag-and-drop data transfer in Windows Presentation Foundation (WPF).

In this walkthrough, you will create a custom WPF UserControl that represents a circle shape. You will implement functionality on the control to enable data transfer through drag-and-drop. For example, if you drag from one Circle control to another, the Fill color data is copied from the source Circle to the target. If you drag from a Circle control to a TextBox, the string representation of the Fill color is copied to the TextBox. You will also create a small application that contains two panel controls and a TextBox to test the drag-and-drop functionality. You will write code that enables the panels to process dropped Circle data, which will enable you to move or copy Circles from the Children collection of one panel to the other.

This walkthrough illustrates the following tasks:

  • Create a custom user control.

  • Enable the user control to be a drag source.

  • Enable the user control to be a drop target.

  • Enable a panel to receive data dropped from the user control.

Prerequisites

You need the following components to complete this walkthrough:

  • Visual Studio 2010

Creating the Application Project

In this section, you will create the application infrastructure, which includes a main page with two panels and a TextBox.

To create the project

  1. Create a new WPF Application project in Visual Basic or Visual C# named DragDropExample. For more information, see How to: Create a New WPF Application Project.

  2. Open MainWindow.xaml.

  3. Add the following markup between the opening and closing Grid tags.

    This markup creates the user interface for the test application.

    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <StackPanel Grid.Column="0"
                Background="Beige">
        <TextBox Width="Auto" Margin="2"
                 Text="green"/>
    </StackPanel>
    <StackPanel Grid.Column="1"
                Background="Bisque">
    </StackPanel>
    

Adding a New User Control to the Project

In this section, you will add a new user control to the project.

To add a new user control

  1. On the Project menu, select Add User Control.

  2. In the Add New Item dialog box, change the name to Circle.xaml, and click Add.

    Circle.xaml and its code-behind is added to the project.

  3. Open Circle.xaml.

    This file will contain the user interface elements of the user control.

  4. Add the following markup to the root Grid to create a simple user control that has a blue circle as its UI.

    <Ellipse x:Name="circleUI" 
             Height="100" Width="100"
             Fill="Blue" />
    
  5. Open Circle.xaml.cs or Circle.xaml.vb.

  6. In C#, add the following code after the default constructor to create a copy constructor. In Visual Basic, add the following code to create both a default constructor and a copy constructor.

    In order to allow the user control to be copied, you add a copy constructor method in the code-behind file. In the simplified Circle user control, you will only copy the Fill and the size of the of the user control.

    public Circle(Circle c)
    {
        InitializeComponent();
        this.circleUI.Height = c.circleUI.Height;
        this.circleUI.Width = c.circleUI.Height;
        this.circleUI.Fill = c.circleUI.Fill;
    }
    

To add the user control to the main window

  1. Open MainWindow.xaml.

  2. Add the following XAML to the opening Window tag to create an XML namespace reference to the current application.

    xmlns:local="clr-namespace:DragDropExample"
    
  3. In the first StackPanel, add the following XAML to create two instances of the Circle user control in the first panel.

    <local:Circle Margin="2" />
    <local:Circle Margin="2" />
    

    The full XAML for the panel looks like the following.

    <StackPanel Grid.Column="0"
                Background="Beige">
        <TextBox Width="Auto" Margin="2"
                 Text="green"/>
        <local:Circle Margin="2" />
        <local:Circle Margin="2" />
    </StackPanel>
    <StackPanel Grid.Column="1"
                Background="Bisque">
    </StackPanel>
    

Implementing Drag Source Events in the User Control

In this section, you will override the OnMouseMove method and initiate the drag-and-drop operation.

If a drag is started (a mouse button is pressed and the mouse is moved), you will package the data to be transferred into a DataObject. In this case, the Circle control will package three data items; a string representation of its Fill color, a double representation of its height, and a copy of itself.

To initiate a drag-and-drop operation

  1. Open Circle.xaml.cs or Circle.xaml.vb.

  2. Add the following OnMouseMove override to provide class handling for the MouseMove event.

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            // Package the data.
            DataObject data = new DataObject();
            data.SetData(DataFormats.StringFormat, circleUI.Fill.ToString());
            data.SetData("Double", circleUI.Height);
            data.SetData("Object", this);
    
            // Inititate the drag-and-drop operation.
            DragDrop.DoDragDrop(this, data, DragDropEffects.Copy | DragDropEffects.Move);
        }
    }
    

    This OnMouseMove override performs the following tasks:

    • Checks whether the left mouse button is pressed while the mouse is moving.

    • Packages the Circle data into a DataObject. In this case, the Circle control packages three data items; a string representation of its Fill color, a double representation of its height, and a copy of itself.

    • Calls the static DragDrop.DoDragDrop method to initiate the drag-and-drop operation. You pass the following three parameters to the DoDragDrop method:

      • dragSource – A reference to this control.

      • data – The DataObject created in the previous code.

      • allowedEffects – The allowed drag-and-drop operations, which are Copy or Move.

  3. Press F5 to build and run the application.

  4. Click one of the Circle controls and drag it over the panels, the other Circle, and the TextBox. When dragging over the TextBox, the cursor changes to indicate a move.

  5. While dragging a Circle over the TextBox, press the CTRL key. Notice how the cursor changes to indicate a copy.

  6. Drag and drop a Circle onto the TextBox. The string representation of the Circle’s fill color is appended to the TextBox.

    String representation of Circle's fill color

By default, the cursor will change during a drag-and-drop operation to indicate what effect dropping the data will have. You can customize the feedback given to the user by handling the GiveFeedback event and setting a different cursor.

To give feedback to the user

  1. Open Circle.xaml.cs or Circle.xaml.vb.

  2. Add the following OnGiveFeedback override to provide class handling for the GiveFeedback event.

    protected override void OnGiveFeedback(GiveFeedbackEventArgs e)
    {
        base.OnGiveFeedback(e);
        // These Effects values are set in the drop target's
        // DragOver event handler.
        if (e.Effects.HasFlag(DragDropEffects.Copy))
        {
            Mouse.SetCursor(Cursors.Cross);
        }
        else if (e.Effects.HasFlag(DragDropEffects.Move))
        {
            Mouse.SetCursor(Cursors.Pen);
        }
        else
        {
            Mouse.SetCursor(Cursors.No);
        }
        e.Handled = true;
    }
    

    This OnGiveFeedback override performs the following tasks:

    • Checks the Effects values that are set in the drop target's DragOver event handler.

    • Sets a custom cursor based on the Effects value. The cursor is intended to give visual feedback to the user about what effect dropping the data will have.

  3. Press F5 to build and run the application.

  4. Drag one of the Circle controls over the panels, the other Circle, and the TextBox. Notice that the cursors are now the custom cursors that you specified in the OnGiveFeedback override.

    Drag and drop with custom cursors
  5. Select the text green from the TextBox.

  6. Drag the green text to a Circle control. Notice that the default cursors are shown to indicate the effects of the drag-and-drop operation. The feedback cursor is always set by the drag source.

Implementing Drop Target Events in the User Control

In this section, you will specify that the user control is a drop target, override the methods that enable the user control to be a drop target, and process the data that is dropped on it.

To enable the user control to be a drop target

  1. Open Circle.xaml.

  2. In the opening UserControl tag, add the AllowDrop property and set it to true.

    <UserControl x:Class="DragDropWalkthrough.Circle"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300"
                 AllowDrop="True">
    

The OnDrop method is called when the AllowDrop property is set to true and data from the drag source is dropped on the Circle user control. In this method, you will process the data that was dropped and apply the data to the Circle.

To process the dropped data

  1. Open Circle.xaml.cs or Circle.xaml.vb.

  2. Add the following OnDrop override to provide class handling for the Drop event.

    protected override void OnDrop(DragEventArgs e)
    {
        base.OnDrop(e);
    
        // If the DataObject contains string data, extract it.
        if (e.Data.GetDataPresent(DataFormats.StringFormat))
        {
            string dataString = (string)e.Data.GetData(DataFormats.StringFormat);
    
            // If the string can be converted into a Brush, 
            // convert it and apply it to the ellipse.
            BrushConverter converter = new BrushConverter();
            if (converter.IsValid(dataString))
            {
                Brush newFill = (Brush)converter.ConvertFromString(dataString);
                circleUI.Fill = newFill;
    
                // Set Effects to notify the drag source what effect
                // the drag-and-drop operation had.
                // (Copy if CTRL is pressed; otherwise, move.)
                if (e.KeyStates.HasFlag(DragDropKeyStates.ControlKey))
                {
                    e.Effects = DragDropEffects.Copy;
                }
                else
                {
                    e.Effects = DragDropEffects.Move;
                }
            }
        }
        e.Handled = true;
    }
    

    This OnDrop override performs the following tasks:

    • Uses the GetDataPresent method to check if the dragged data contains a string object.

    • Uses the GetData method to extract the string data if it is present.

    • Uses a BrushConverter to try to convert the string to a Brush.

    • If the conversion is successful, applies the brush to the Fill of the Ellipse that provides the UI of the Circle control.

    • Marks the Drop event as handled. You should mark the drop event as handled so that other elements that receive this event know that the Circle user control handled it.

  3. Press F5 to build and run the application.

  4. Select the text green in the TextBox.

  5. Drag the text to a Circle control and drop it. The Circle changes from blue to green.

    Convert a string to a brush
  6. Type the text green in the TextBox.

  7. Select the text gre in the TextBox.

  8. Drag it to a Circle control and drop it. Notice that the cursor changes to indicate that the drop is allowed, but the color of the Circle does not change because gre is not a valid color.

  9. Drag from the green Circle control and drop on the blue Circle control. The Circle changes from blue to green. Notice that which cursor is shown depends on whether the TextBox or the Circle is the drag source.

Setting the AllowDrop property to true and processing the dropped data is all that is required to enable an element to be a drop target. However, to provide a better user experience, you should also handle the DragEnterDragLeave, and DragOver events. In these events, you can perform checks and provide additional feedback to the user before the data is dropped.

When data is dragged over the Circle user control, the control should notify the drag source whether it can process the data that is being dragged. If the control does not know how to process the data, it should refuse the drop. To do this, you will handle the DragOver event and set the Effectsproperty.

To verify that the data drop is allowed

  1. Open Circle.xaml.cs or Circle.xaml.vb.

  2. Add the following OnDragOver override to provide class handling for the DragOver event.

    protected override void OnDragOver(DragEventArgs e)
    {
        base.OnDragOver(e);
        e.Effects = DragDropEffects.None;
    
        // If the DataObject contains string data, extract it.
        if (e.Data.GetDataPresent(DataFormats.StringFormat))
        {
            string dataString = (string)e.Data.GetData(DataFormats.StringFormat);
    
            // If the string can be converted into a Brush, allow copying or moving.
            BrushConverter converter = new BrushConverter();
            if (converter.IsValid(dataString))
            {
                // Set Effects to notify the drag source what effect
                // the drag-and-drop operation will have. These values are 
                // used by the drag source's GiveFeedback event handler.
                // (Copy if CTRL is pressed; otherwise, move.)
                if (e.KeyStates.HasFlag(DragDropKeyStates.ControlKey))
                {
                    e.Effects = DragDropEffects.Copy;
                }
                else
                {
                    e.Effects = DragDropEffects.Move;
                }
            }
        }
        e.Handled = true;
    }
    

    This OnDragOver override performs the following tasks:

    • Sets the Effects property to None.

    • Performs the same checks that are performed in the OnDrop method to determine whether the Circle user control can process the dragged data.

    • If the user control can process the data, sets the Effects property to Copy or Move.

  3. Press F5 to build and run the application.

  4. Select the text gre in the TextBox.

  5. Drag the text to a Circle control. Notice that the cursor now changes to indicate that the drop is not allowed because gre is not a valid color.

You can further enhance the user experience by applying a preview of the drop operation. For the Circle user control, you will override the OnDragEnter and OnDragLeave methods. When the data is dragged over the control, the current background Fill is saved in a placeholder variable. The string is then converted to a brush and applied to the Ellipse that provides the Circle's UI. If the data is dragged out of the Circle without being dropped, the original Fill value is re-applied to the Circle.

To preview the effects of the drag-and-drop operation

  1. Open Circle.xaml.cs or Circle.xaml.vb.

  2. In the Circle class, declare a private Brush variable named _previousFill and initialize it to null.

    public partial class Circle : UserControl
    {
        private Brush _previousFill = null;
    
  3. Add the following OnDragEnter override to provide class handling for the DragEnter event.

    protected override void OnDragEnter(DragEventArgs e)
    {
        base.OnDragEnter(e);
        // Save the current Fill brush so that you can revert back to this value in DragLeave.
        _previousFill = circleUI.Fill;
    
        // If the DataObject contains string data, extract it.
        if (e.Data.GetDataPresent(DataFormats.StringFormat))
        {
            string dataString = (string)e.Data.GetData(DataFormats.StringFormat);
    
            // If the string can be converted into a Brush, convert it.
            BrushConverter converter = new BrushConverter();
            if (converter.IsValid(dataString))
            {
                Brush newFill = (Brush)converter.ConvertFromString(dataString.ToString());
                circleUI.Fill = newFill;
            }
        }
    }
    

    This OnDragEnter override performs the following tasks:

    • Saves the Fill property of the Ellipse in the _previousFill variable.

    • Performs the same checks that are performed in the OnDrop method to determine whether the data can be converted to a Brush.

    • If the data is converted to a valid Brush, applies it to the Fill of the Ellipse.

  4. Add the following OnDragLeave override to provide class handling for the DragLeave event.

    protected override void OnDragLeave(DragEventArgs e)
    {
        base.OnDragLeave(e);
        // Undo the preview that was applied in OnDragEnter.
        circleUI.Fill = _previousFill;
    }
    

    This OnDragLeave override performs the following tasks:

    • Applies the Brush saved in the _previousFill variable to the Fill of the Ellipse that provides the UI of the Circle user control.

  5. Press F5 to build and run the application.

  6. Select the text green in the TextBox.

  7. Drag the text over a Circle control without dropping it. The Circle changes from blue to green. 

    Preview the effects of a drag-and-drop operation
  8. Drag the text away from the Circle control. The Circle changes from green back to blue.

Enabling a Panel to Receive Dropped Data

In this section, you will enable the panels that host the Circle user controls to act as drop targets for dragged Circle data. You will implement code that enables you to move a Circle from one panel to another, or to make a copy of a Circle control by holding down the CTRL key while dragging and dropping a Circle.

To enable the panel to be a drop target

  1. Open MainWindow.xaml.

  2. As shown in the following XAML, in each of the StackPanel controls, add handlers for the DragOver and Drop events. Name the DragOverevent handler, panel_DragOver, and name the Drop event handler, panel_Drop.

    <StackPanel Grid.Column="0"
                Background="Beige"
                AllowDrop="True"
                DragOver="panel_DragOver"
                Drop="panel_Drop">
        <TextBox Width="Auto" Margin="2"
                 Text="green"/>
        <local:Circle Margin="2" />
        <local:Circle Margin="2" />
    </StackPanel>
    <StackPanel Grid.Column="1"
                Background="Bisque"
                AllowDrop="True"
                DragOver="panel_DragOver"
                Drop="panel_Drop">
    </StackPanel>
    
  3. Open MainWindows.xaml.cs or MainWindow.xaml.vb.

  4. Add the following code for the DragOver event handler.

    private void panel_DragOver(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent("Object"))
        {
            // These Effects values are used in the drag source's
            // GiveFeedback event handler to determine which cursor to display.
            if (e.KeyStates == DragDropKeyStates.ControlKey)
            {
                e.Effects = DragDropEffects.Copy;
            }
            else
            {
                e.Effects = DragDropEffects.Move;
            }
        }
    }
    

    This DragOver event handler performs the following tasks:

    • Checks that the dragged data contains the "Object" data that was packaged in the DataObject by the Circle user control and passed in the call to DoDragDrop.

    • If the "Object" data is present, checks whether the CTRL key is pressed.

    • If the CTRL key is pressed, sets the Effects property to Copy. Otherwise, set the Effects property to Move.

  5. Add the following code for the Drop event handler.

    private void panel_Drop(object sender, DragEventArgs e)
    {
        // If an element in the panel has already handled the drop,
        // the panel should not also handle it.
        if (e.Handled == false)
        {
            Panel _panel = (Panel)sender;
            UIElement _element = (UIElement)e.Data.GetData("Object");
    
            if (_panel != null && _element != null)
            {
                // Get the panel that the element currently belongs to,
                // then remove it from that panel and add it the Children of
                // the panel that its been dropped on.
                Panel _parent = (Panel)VisualTreeHelper.GetParent(_element);
    
                if (_parent != null)
                {
                    if (e.KeyStates == DragDropKeyStates.ControlKey &&
                        e.AllowedEffects.HasFlag(DragDropEffects.Copy))
                    {
                        Circle _circle = new Circle((Circle)_element);
                        _panel.Children.Add(_circle);
                        // set the value to return to the DoDragDrop call
                        e.Effects = DragDropEffects.Copy;
                    }
                    else if (e.AllowedEffects.HasFlag(DragDropEffects.Move))
                    {
                        _parent.Children.Remove(_element);
                        _panel.Children.Add(_element);
                        // set the value to return to the DoDragDrop call
                        e.Effects = DragDropEffects.Move;
                    }
                }
            }
        }
    }
    

    This Drop event handler performs the following tasks:

    • Checks whether the Drop event has already been handled. For instance, if a Circle is dropped on another Circle which handles the Drop event, you do not want the panel that contains the Circle to also handle it.

    • If the Drop event is not handled, checks whether the CTRL key is pressed.

    • If the CTRL key is pressed when the Drop happens, makes a copy of the Circle control and add it to the Children collection of the StackPanel.

    • If the CTRL key is not pressed, moves the Circle from the Children collection of its parent panel to the Children collection of the panel that it was dropped on.

    • Sets the Effects property to notify the DoDragDrop method whether a move or copy operation was performed.

  6. Press F5 to build and run the application.

  7. Select the text green from the TextBox.

  8. Drag the text over a Circle control and drop it.

  9. Drag a Circle control from the left panel to the right panel and drop it. The Circle is removed from the Children collection of the left panel and added to the Children collection of the right panel.

  10. Drag a Circle control from the panel it is in to the other panel and drop it while pressing the CTRL key. The Circle is copied and the copy is added to the Children collection of the receiving panel.

    Dragging a Circle while pressing the CTRL key





How to: Open a File That is Dropped on a RichTextBox Control


In Windows Presentation Foundation (WPF), the TextBoxRichTextBox, and FlowDocument controls all have built-in drag-and-drop functionality. The built-in functionality enables drag-and-drop of text within and between the controls. However, it does not enable opening a file by dropping the file on the control. These controls also mark the drag-and-drop events as handled. As a result, by default, you cannot add your own event handlers to provide functionality to open dropped files.

To add additional handling for drag-and-drop events in these controls, use the AddHandler(RoutedEvent, Delegate, Boolean) method to add your event handlers for the drag-and-drop events. Set the handledEventsToo parameter to true to have the specified handler be invoked for a routed event that has already been marked as handled by another element along the event route.

System_CAPS_tipTip

You can replace the built-in drag-and-drop functionality of TextBoxRichTextBox, and FlowDocument by handling the preview versions of the drag-and-drop events and marking the preview events as handled. However, this will disable the built-in drag-and-drop functionality, and is not recommended.

Example

The following example demonstrates how to add handlers for the DragOver and Drop events on a RichTextBox. This example uses the AddHandler(RoutedEvent, Delegate, Boolean) method and sets the handledEventsToo parameter to true so that the events handlers will be invoked even though the RichTextBox marks these events as handled. The code in the event handlers adds functionality to open a text file that is dropped on the RichTextBox.

To test this example, drag a text file or a rich text format (RTF) file from Windows Explorer to the RichTextBox. The file will be opened in the RichTextBox. If you press the SHIFT key before the dropping the file, the file will be opened as plain text.

<RichTextBox x:Name="richTextBox1"
             AllowDrop="True" />
public MainWindow()
{
    InitializeComponent();

    // Add using System.Windows.Controls;
    richTextBox1.AddHandler(RichTextBox.DragOverEvent, new DragEventHandler(RichTextBox_DragOver), true);
    richTextBox1.AddHandler(RichTextBox.DropEvent, new DragEventHandler(RichTextBox_Drop), true);
}

private void RichTextBox_DragOver(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        e.Effects = DragDropEffects.All;
    }
    else
    {
        e.Effects = DragDropEffects.None;
    }
    e.Handled = false;
}

private void RichTextBox_Drop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        string[] docPath = (string[])e.Data.GetData(DataFormats.FileDrop);

        // By default, open as Rich Text (RTF).
        var dataFormat = DataFormats.Rtf;

        // If the Shift key is pressed, open as plain text.
        if (e.KeyStates == DragDropKeyStates.ShiftKey)
        {
            dataFormat = DataFormats.Text;
        }

        System.Windows.Documents.TextRange range;
        System.IO.FileStream fStream;
        if (System.IO.File.Exists(docPath[0]))
        {
            try
            {
                // Open the document in the RichTextBox.
                range = new System.Windows.Documents.TextRange(richTextBox1.Document.ContentStart, richTextBox1.Document.ContentEnd);
                fStream = new System.IO.FileStream(docPath[0], System.IO.FileMode.OpenOrCreate);
                range.Load(fStream, dataFormat);
                fStream.Close();
            }
            catch (System.Exception)
            {
                MessageBox.Show("File could not be opened. Make sure the file is a text file.");
            }
        }
    }
}





How to: Create a Data Object


The following examples show various ways to create a data object using the constructors provided by the DataObject class.

Example

Description

The following example code creates a new data object and uses one of the overloaded constructors (DataObject(Object)) to initialize the data object with a string. In this case, an appropriate data format is determined automatically according to the stored data's type, and auto-converting of the stored data is allowed by default.

Code

string stringData = "Some string data to store...";
DataObject dataObject = new DataObject(stringData);

Description

The following example code is a condensed version of the code shown above.

Code

DataObject dataObject = new DataObject("Some string data to store...");

Example

Description

The following example code creates a new data object and uses one of the overloaded constructors (DataObject(String, Object)) to initialize the data object with a string and a specified data format. In this case the data format is specified by a string; the DataFormats class provides a set of pre-defined type strings. Auto-converting of the stored data is allowed by default.

Code

string stringData = "Some string data to store...";
string dataFormat = DataFormats.UnicodeText;
DataObject dataObject = new DataObject(dataFormat, stringData);

Description

The following example code is a condensed version of the code shown above.

Code

DataObject dataObject = new DataObject(DataFormats.UnicodeText, "Some string data to store...");

Example

Description

The following example code creates a new data object and uses one of the overloaded constructors (DataObject) to initialize the data object with a string and a specified data format. In this case the data format is specified by a Type parameter. Auto-converting of the stored data is allowed by default.

Code

string stringData = "Some string data to store...";
Type dataFormat = stringData.GetType();
DataObject dataObject = new DataObject(dataFormat, stringData);

Description

The following example code is a condensed version of the code shown above.

Code

DataObject dataObject = new DataObject("".GetType(), "Some string data to store...");

Example

Description

The following example code creates a new data object and uses one of the overloaded constructors (DataObject(String, Object, Boolean)) to initialize the data object with a string and a specified data format. In this case the data format is specified by a string; the DataFormats class provides a set of pre-defined type strings. This particular constructor overload enables the caller to specify whether auto-converting is allowed.

Code

string stringData = "Some string data to store...";
string dataFormat = DataFormats.Text;
bool autoConvert = false;
DataObject dataObject = new DataObject(dataFormat, stringData, autoConvert);

Description

The following example code is a condensed version of the code shown above.

Code

DataObject dataObject = new DataObject(DataFormats.Text, "Some string data to store...", false);






How to: Determine if a Data Format is Present in a Data Object


The following examples show how to use the various GetDataPresent method overloads to query whether a particular data format is present in a data object.

Example

Description

The following example code uses the GetDataPresent(String) overload to query for the presence of a particular data format by descriptor string.

Code

DataObject dataObject = new DataObject("Some string data to store...");

// Query for the presence of Text data in the data object, by a data format descriptor string.
// In this overload of GetDataPresent, the method will return true both for native data formats
// and when the data can automatically be converted to the specifed format.

// In this case, string data is present natively, so GetDataPresent returns "true".
string textData = null;
if (dataObject.GetDataPresent(DataFormats.StringFormat))
{
    textData = dataObject.GetData(DataFormats.StringFormat) as string;
}

// In this case, the Text data in the data object can be autoconverted to 
// Unicode text, so GetDataPresent returns "true".
byte[] unicodeData = null;
if (dataObject.GetDataPresent(DataFormats.UnicodeText))
{
    unicodeData = dataObject.GetData(DataFormats.UnicodeText) as byte[];
}

Example

Description

The following example code uses the GetDataPresent(Type) overload to query for the presence of a particular data format by type.

Code

DataObject dataObject = new DataObject("Some string data to store...");

// Query for the presence of String data in the data object, by type.  In this overload 
// of GetDataPresent, the method will return true both for native data formats
// and when the data can automatically be converted to the specifed format.

// In this case, the Text data present in the data object can be autoconverted
// to type string (also represented by DataFormats.String), so GetDataPresent returns "true".
string stringData = null;
if (dataObject.GetDataPresent(typeof(string)))
{
    stringData = dataObject.GetData(DataFormats.Text) as string;
}

Example

Description

The following example code uses the GetDataPresent(String, Boolean) overload to query for data by descriptor string, and specifying how to treat auto-convertible data formats.

Code

DataObject dataObject = new DataObject("Some string data to store...");

// Query for the presence of Text data in the data object, by data format descriptor string,
// and specifying whether auto-convertible data formats are acceptable.  

// In this case, Text data is present natively, so GetDataPresent returns "true".
string textData = null;
if (dataObject.GetDataPresent(DataFormats.Text, false /* Auto-convert? */))
{
    textData = dataObject.GetData(DataFormats.Text) as string;
}

// In this case, the Text data in the data object can be autoconverted to 
// Unicode text, but it is not available natively, so GetDataPresent returns "false".
byte[] unicodeData = null;
if (dataObject.GetDataPresent(DataFormats.UnicodeText, false /* Auto-convert? */))
{
    unicodeData = dataObject.GetData(DataFormats.UnicodeText) as byte[];
}

// In this case, the Text data in the data object can be autoconverted to 
// Unicode text, so GetDataPresent returns "true".
if (dataObject.GetDataPresent(DataFormats.UnicodeText, true /* Auto-convert? */))
{
    unicodeData = dataObject.GetData(DataFormats.UnicodeText) as byte[];
}





How to: List the Data Formats in a Data Object


The following examples show how to use the GetFormats method overloads get an array of strings denoting each data format that is available in a data object.

Example

Description

The following example code uses the GetFormats overload to get an array of strings denoting all data formats available in a data object (both native and auto-convertible).

Code

DataObject dataObject = new DataObject("Some string data to store...");

// Get an array of strings, each string denoting a data format
// that is available in the data object.  This overload of GetDataFormats
// returns all available data formats, native and auto-convertible.
string[] dataFormats = dataObject.GetFormats();

// Get the number of data formats present in the data object, including both
// auto-convertible and native data formats.
int numberOfDataFormats = dataFormats.Length;

// To enumerate the resulting array of data formats, and take some action when
// a particular data format is found, use a code structure similar to the following.
foreach (string dataFormat in dataFormats)
{
    if (dataFormat == DataFormats.Text)
    {
        // Take some action if/when data in the Text data format is found.
        break;
    }
    else if(dataFormat == DataFormats.StringFormat)
    {
        // Take some action if/when data in the string data format is found.
        break;
    }
}

Example

Description

The following example code uses the GetFormats overload to get an array of strings denoting only data formats available in a data object (auto-convertible data formats are filtered).

Code

DataObject dataObject = new DataObject("Some string data to store...");

// Get an array of strings, each string denoting a data format
// that is available in the data object.  This overload of GetDataFormats
// accepts a Boolean parameter inidcating whether to include auto-convertible
// data formats, or only return native data formats.
string[] dataFormats = dataObject.GetFormats(false /* Include auto-convertible? */);

// Get the number of native data formats present in the data object.
int numberOfDataFormats = dataFormats.Length;

// To enumerate the resulting array of data formats, and take some action when
// a particular data format is found, use a code structure similar to the following.
foreach (string dataFormat in dataFormats)
{
    if (dataFormat == DataFormats.Text)
    {
        // Take some action if/when data in the Text data format is found.
        break;
    }
}





How to: Retrieve Data in a Particular Data Format


The following examples show how to retrieve data from a data object in a specified format.

Example

Description

The following example code uses the GetDataPresent(String) overload to first check if a specified data format is available (natively or by auto-convert); if the specified format is available, the example retrieves the data by using the GetData(String) method.

Code

DataObject dataObject = new DataObject("Some string data to store...");

string desiredFormat = DataFormats.UnicodeText;
byte[] data = null;

// Use the GetDataPresent method to check for the presence of a desired data format.
// This particular overload of GetDataPresent looks for both native and auto-convertible 
// data formats.
if (dataObject.GetDataPresent(desiredFormat))
{
    // If the desired data format is present, use one of the GetData methods to retrieve the
    // data from the data object.
    data = dataObject.GetData(desiredFormat) as byte[];
}

Example

Description

The following example code uses the GetDataPresent(String, Boolean) overload to first check if a specified data format is available natively (auto-convertible data formats are filtered); if the specified format is available, the example retrieves the data by using the GetData(String) method.

Code

DataObject dataObject = new DataObject("Some string data to store...");

string desiredFormat = DataFormats.UnicodeText;
bool noAutoConvert = false;
byte[] data = null;

// Use the GetDataPresent method to check for the presence of a desired data format.
// The autoconvert parameter is set to false to filter out auto-convertible data formats,
// returning true only if the specified data format is available natively.
if (dataObject.GetDataPresent(desiredFormat, noAutoConvert))
{
    // If the desired data format is present, use one of the GetData methods to retrieve the
    // data from the data object.
    data = dataObject.GetData(desiredFormat) as byte[];
}





How to: Store Multiple Data Formats in a Data Object


The following example shows how to use the SetData(String, Object) method to add data to a data object in multiple formats.

Example

Code

DataObject dataObject = new DataObject();
string sourceData = "Some string data to store...";

// Encode the source string into Unicode byte arrays.
byte[] unicodeText = Encoding.Unicode.GetBytes(sourceData); // UTF-16
byte[] utf8Text = Encoding.UTF8.GetBytes(sourceData);
byte[] utf32Text = Encoding.UTF32.GetBytes(sourceData);

// The DataFormats class does not provide data format fields for denoting
// UTF-32 and UTF-8, which are seldom used in practice; the following strings 
// will be used to identify these "custom" data formats.
string utf32DataFormat = "UTF-32";
string utf8DataFormat  = "UTF-8";

// Store the text in the data object, letting the data object choose
// the data format (which will be DataFormats.Text in this case).
dataObject.SetData(sourceData);
// Store the Unicode text in the data object.  Text data can be automatically
// converted to Unicode (UTF-16 / UCS-2) format on extraction from the data object; 
// Therefore, explicitly converting the source text to Unicode is generally unnecessary, and
// is done here as an exercise only.
dataObject.SetData(DataFormats.UnicodeText, unicodeText);
// Store the UTF-8 text in the data object...
dataObject.SetData(utf8DataFormat, utf8Text);
// Store the UTF-32 text in the data object...
dataObject.SetData(utf32DataFormat, utf32Text);







:
Posted by 지훈2