Перетаскивание (Drag and Drop)
68WPF --- Основа WPF --- Перетаскивание (Drag and Drop)
Операции перетаскивания (способ извлечения информации из одного места в окне и помещения ее в другое место) сегодня не являются столь распространенными, как несколько лет назад. Программисты постепенно перешли на другие методы копирования информации, которые не требуют удержания нажатой кнопки мыши (многим пользователям это удается с трудом). Программы, которые поддерживают перетаскивание, часто предлагают его как быстрый вариант для опытных пользователей, а не как стандартный способ работы.
Операции перетаскивания в WPF не претерпели существенных изменений. Если вы использовали их в приложениях Windows Forms, то увидите, что программный интерфейс в WPF остался практически таким же. Ключевым отличием является то, что методы и события, используемые в операциях перетаскивания, сосредоточены в классе System.Windows.DragDrop и через него доступны другим классам (например, UIElement).
По сути, операция перетаскивания выполняется в три этапа:
Пользователь щелкает на элементе (или выделяет некоторую область внутри него) и удерживает прижатой кнопку мыши. В этот момент сохраняется некоторая информация и начинается выполнение операции перетаскивания.
Пользователь перемещает указатель на другой элемент. Если этот элемент может принимать тип перетаскиваемого содержимого (например, изображение или фрагмент текста), указатель мыши принимает вид значка перетаскивания. Иначе указатель мыши принимает вид перечеркнутого кружка.
Когда пользователь отпускает кнопку мыши, элемент получает информацию и принимает решение о дальнейшей ее судьбе. Эту операцию можно отменить, нажав клавишу <Esc> (когда кнопка мыши еще не отпущена).
Вы можете попробовать, как работает перетаскивание, добавив в окно два объекта TextBox, т.к. элемент TextBox имеет встроенную логику для поддержки операции перетаскивания. Если выбрать фрагмент текста внутри текстового поля, то его можно перетащить в другое текстовое поле. Когда вы отпустите кнопку мыши, текст будет перемещен. Те же принципы распространяются и на взаимодействие приложений — например, можно перетащить кусок текста из документа Word в объект WPF TextBox, или наоборот.
Иногда бывает необходимо разрешить перетаскивание между элементами, не обладающими такой встроенной возможностью. Например, нужно сделать так, чтобы пользователь мог перетаскивать содержимое из текстового поля на метку. В такой ситуации придется обрабатывать события перетаскивания:
<Canvas>
<Label Name="lbl2" Canvas.Top="100" Canvas.Left="30" Padding="10"
BorderBrush="LightBlue" BorderThickness="2" MouseDown="lbl1_MouseDown">Всем пока (</Label>
<Label Name="lbl1" Canvas.Top="40" Canvas.Left="30" Padding="10"
BorderBrush="LightBlue" BorderThickness="2" MouseDown="lbl1_MouseDown">Всем привет!</Label>
<Border Canvas.Top="75" Canvas.Left="250" BorderBrush="Black" BorderThickness="2">
<TextBlock MinWidth="100" MinHeight="30" FontSize="16"
Name="txtTarget" AllowDrop="True" Drop="txtTarget_Drop"></TextBlock>
</Border>
</Canvas>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void lbl1_MouseDown(object sender, MouseButtonEventArgs e)
{
Label lbl = (Label)sender;
DragDrop.DoDragDrop(lbl, lbl.Content, DragDropEffects.Copy);
}
private void txtTarget_Drop(object sender, DragEventArgs e)
{
((TextBlock)sender).Text = (string)e.Data.GetData(DataFormats.Text);
}
}
У операции перетаскивания есть две стороны: источник и цель. Чтобы создать источник перетаскивания, нужно в некоторый момент вызвать метод DragDrop.DoDragDrop(), чтобы начать операцию перетаскивания. В этот момент идентифицируется источник для операции перетаскивания, выбирается содержимое, которое нужно переместить, и задаются разрешенные при перетаскивании эффекты (копирование, перемещение и т.д.).
Обычно метод DoDragDrop() вызывается в ответ на событие MouseDown или PreviewMouseDown. Для операции перетаскивания используется текстовое содержимое метки.
Свойство AllowDrop элемента, который принимает данные, должно иметь значение true. Кроме того, этот элемент должен обработать событие Drop, чтобы оперировать данными.



Когда свойству AllowDrop присваивается значение true, элементу разрешается принимать любой тип информации. Если нужны большие возможности, можно обрабатывать событие DragEnter. В этот момент можно проверить тип перетаскиваемых данных, а затем определить тип разрешаемой операции.
Операция перетаскивания позволяет обмениваться объектами любых типов. Этот вольный подход вполне годится для ваших приложений, но его не рекомендуется применять, если вам нужно сообщаться с другими приложениями. В этом случае следует использовать один из базовых типов данных (например, строки, целые числа и т.п.) или объект, который реализует интерфейс ISerializable или IDataObject (что позволит .NET передавать ваш объект в виде потока байтов и заново создавать объект в домене другого приложения). Интересным приемом является преобразование элемента WPF в XAML с последующей его реконструкцией в другом месте. Все, что для этого нужно — объекты XamlWriter и XamlReader.