Bagikan melalui


Panduan: Mengaktifkan Seret dan Lepaskan pada Kontrol Pengguna

Panduan ini menunjukkan cara membuat kontrol pengguna kustom yang dapat berpartisipasi dalam transfer data seret dan letakkan di Windows Presentation Foundation (WPF).

Dalam panduan ini, Anda akan membuat WPF UserControl kustom yang mewakili bentuk lingkaran. Anda akan menerapkan fungsionalitas pada kontrol untuk mengaktifkan transfer data melalui seret dan letakkan. Misalnya, jika Anda menyeret dari satu kontrol Lingkaran ke kontrol Lingkaran lainnya, data Warna isian disalin dari Lingkaran sumber ke target. Jika Anda menyeret dari kontrol Lingkaran ke TextBox, representasi string warna Isian disalin ke TextBox. Anda juga akan membuat aplikasi kecil yang berisi dua kontrol panel dan TextBox untuk menguji fungsionalitas seret dan letakkan. Anda akan menulis kode yang memungkinkan panel memproses data Lingkaran yang dihilangkan, yang akan memungkinkan Anda memindahkan atau menyalin Lingkaran dari kumpulan Anak dari satu panel ke panel lainnya.

Panduan ini mengilustrasikan tugas-tugas berikut:

  • Buat kontrol pengguna kustom.

  • Aktifkan kontrol pengguna untuk menjadi sumber seret.

  • Aktifkan kontrol pengguna untuk menjadi target penghilangan.

  • Aktifkan panel untuk menerima data yang dihilangkan dari kontrol pengguna.

Prasyarat

Anda memerlukan Visual Studio untuk menyelesaikan panduan ini.

Membuat Proyek Aplikasi

Di bagian ini, Anda akan membuat infrastruktur aplikasi, yang mencakup halaman utama dengan dua panel dan TextBox.

  1. Buat proyek Aplikasi WPF baru di Visual Basic atau Visual C# bernama DragDropExample. Untuk informasi selengkapnya, lihat Panduan: Aplikasi desktop WPF pertama saya.

  2. Buka MainWindow.xaml.

  3. Tambahkan markup berikut antara tag pembuka dan penutup Grid .

    Markup ini membuat antarmuka pengguna untuk aplikasi pengujian.

    <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>
    

Menambahkan Kontrol Pengguna Baru ke Proyek

Di bagian ini, Anda akan menambahkan kontrol pengguna baru ke proyek.

  1. Pada menu Proyek, pilih Tambahkan Kontrol Pengguna.

  2. Dalam kotak dialog Tambahkan Item Baru, ubah nama menjadi Circle.xaml, dan klik Tambahkan.

    Circle.xaml dan code-behind-nya ditambahkan ke proyek.

  3. Buka Circle.xaml.

    File ini akan berisi elemen antarmuka pengguna kontrol pengguna.

  4. Tambahkan markup berikut ke akar Grid untuk membuat kontrol pengguna sederhana yang memiliki lingkaran biru sebagai UI-nya.

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

  6. Di C#, tambahkan kode berikut setelah konstruktor tanpa parameter untuk membuat konstruktor salinan. Di Visual Basic, tambahkan kode berikut untuk membuat konstruktor tanpa parameter dan konstruktor salinan.

    Untuk mengizinkan kontrol pengguna disalin, Anda menambahkan metode konstruktor salinan dalam file code-behind. Dalam kontrol pengguna Lingkaran yang disederhanakan, Anda hanya akan menyalin Isi dan ukuran kontrol pengguna.

    public Circle(Circle c)
    {
        InitializeComponent();
        this.circleUI.Height = c.circleUI.Height;
        this.circleUI.Width = c.circleUI.Height;
        this.circleUI.Fill = c.circleUI.Fill;
    }
    
    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()
    End Sub
    
    Public Sub New(ByVal c As Circle)
        InitializeComponent()
        Me.circleUI.Height = c.circleUI.Height
        Me.circleUI.Width = c.circleUI.Height
        Me.circleUI.Fill = c.circleUI.Fill
    End Sub
    

Menambahkan kontrol pengguna ke jendela utama

  1. Buka MainWindow.xaml.

  2. Tambahkan XAML berikut ke tag pembuka Window untuk membuat referensi namespace XML ke aplikasi saat ini.

    xmlns:local="clr-namespace:DragDropExample"
    
  3. Di bagian pertama StackPanel, tambahkan XAML berikut untuk membuat dua instans kontrol pengguna Circle di panel pertama.

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

    XAML lengkap untuk panel terlihat seperti berikut ini.

    <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>
    

Menerapkan Peristiwa Seret Sumber di Kontrol Pengguna

Di bagian ini, Anda akan mengambil alih OnMouseMove metode dan memulai operasi seret dan letakkan.

Jika seret dimulai (tombol mouse ditekan dan mouse dipindahkan), Anda akan mengemas data yang akan ditransfer ke dalam DataObject. Dalam hal ini, kontrol Lingkaran akan mengemas tiga item data; representasi string dari warna Isiannya, representasi ganda dari tingginya, dan salinannya sendiri.

Untuk memulai operasi seret dan letakkan

  1. Buka Circle.xaml.cs atau Circle.xaml.vb.

  2. Tambahkan penimpaan berikut OnMouseMove untuk menyediakan penanganan kelas untuk peristiwa tersebut MouseMove .

    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);
    
            // Initiate the drag-and-drop operation.
            DragDrop.DoDragDrop(this, data, DragDropEffects.Copy | DragDropEffects.Move);
        }
    }
    
    Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Input.MouseEventArgs)
        MyBase.OnMouseMove(e)
        If e.LeftButton = MouseButtonState.Pressed Then
            ' Package the data.
            Dim data As New DataObject
            data.SetData(DataFormats.StringFormat, circleUI.Fill.ToString())
            data.SetData("Double", circleUI.Height)
            data.SetData("Object", Me)
    
            ' Inititate the drag-and-drop operation.
            DragDrop.DoDragDrop(Me, data, DragDropEffects.Copy Or DragDropEffects.Move)
        End If
    End Sub
    

    Penimpaan ini OnMouseMove melakukan tugas-tugas berikut:

    • Memeriksa apakah tombol mouse kiri ditekan saat mouse bergerak.

    • Mengemas data Lingkaran ke dalam DataObject. Dalam hal ini, kontrol Lingkaran mengemas tiga item data; representasi string dari warna Isiannya, representasi ganda dari tingginya, dan salinannya sendiri.

    • Memanggil metode statis DragDrop.DoDragDrop untuk memulai operasi seret dan letakkan. Anda meneruskan tiga parameter berikut ke DoDragDrop metode :

      • dragSource – Referensi ke kontrol ini.

      • data – yang DataObject dibuat dalam kode sebelumnya.

      • allowedEffects – Operasi seret dan letakkan yang diizinkan, yaitu Copy atau Move.

  3. Tekan F5 untuk membangun dan menjalankan aplikasi.

  4. Klik salah satu kontrol Lingkaran dan seret ke atas panel, Lingkaran lainnya, dan TextBox. Saat menyeret ke TextBoxatas , kursor berubah untuk menunjukkan pemindahan.

  5. Saat menyeret Lingkaran ke TextBoxatas , tekan tombol Ctrl . Perhatikan bagaimana kursor berubah untuk menunjukkan salinan.

  6. Seret dan letakkan Lingkaran ke TextBox. Representasi string dari warna isian Lingkaran ditambahkan ke TextBox.

    String representation of Circle's fill color

Secara default, kursor akan berubah selama operasi seret dan letakkan untuk menunjukkan efek apa yang akan dimiliki data. Anda dapat menyesuaikan umpan balik yang diberikan kepada pengguna dengan menangani GiveFeedback peristiwa dan mengatur kursor yang berbeda.

Memberikan umpan balik kepada pengguna

  1. Buka Circle.xaml.cs atau Circle.xaml.vb.

  2. Tambahkan penimpaan berikut OnGiveFeedback untuk menyediakan penanganan kelas untuk peristiwa tersebut GiveFeedback .

    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;
    }
    
    Protected Overrides Sub OnGiveFeedback(ByVal e As System.Windows.GiveFeedbackEventArgs)
        MyBase.OnGiveFeedback(e)
        ' These Effects values are set in the drop target's
        ' DragOver event handler.
        If e.Effects.HasFlag(DragDropEffects.Copy) Then
            Mouse.SetCursor(Cursors.Cross)
        ElseIf e.Effects.HasFlag(DragDropEffects.Move) Then
            Mouse.SetCursor(Cursors.Pen)
        Else
            Mouse.SetCursor(Cursors.No)
        End If
        e.Handled = True
    End Sub
    

    Penimpaan ini OnGiveFeedback melakukan tugas-tugas berikut:

    • Effects Memeriksa nilai yang diatur dalam penanganan aktivitas target DragOver drop.

    • Mengatur kursor kustom berdasarkan Effects nilai . Kursor dimaksudkan untuk memberikan umpan balik visual kepada pengguna tentang efek apa yang akan dimiliki data.

  3. Tekan F5 untuk membangun dan menjalankan aplikasi.

  4. Seret salah satu kontrol Lingkaran di atas panel, Lingkaran lainnya, dan TextBox. Perhatikan bahwa kursor sekarang menjadi kursor kustom yang Anda tentukan dalam penimpaan OnGiveFeedback .

    Drag and drop with custom cursors

  5. Pilih teks green dari TextBox.

  6. green Seret teks ke kontrol Lingkaran. Perhatikan bahwa kursor default ditampilkan untuk menunjukkan efek operasi seret dan letakkan. Kursor umpan balik selalu diatur oleh sumber seret.

Menerapkan Peristiwa Target Drop di Kontrol Pengguna

Di bagian ini, Anda akan menentukan bahwa kontrol pengguna adalah target penghilangan, mengambil alih metode yang memungkinkan kontrol pengguna menjadi target penurunan, dan memproses data yang dihilangkan di atasnya.

Untuk mengaktifkan kontrol pengguna menjadi target penghilangan

  1. Buka Circle.xaml.

  2. Di tag pembuka UserControl , tambahkan AllowDrop properti dan atur ke 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">
    

Metode OnDrop ini dipanggil ketika AllowDrop properti diatur ke true dan data dari sumber seret dihilangkan pada kontrol pengguna Lingkaran. Dalam metode ini, Anda akan memproses data yang dihilangkan dan menerapkan data ke Lingkaran.

Untuk memproses data yang dihilangkan

  1. Buka Circle.xaml.cs atau Circle.xaml.vb.

  2. Tambahkan penimpaan berikut OnDrop untuk menyediakan penanganan kelas untuk peristiwa tersebut Drop .

    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;
    }
    
    Protected Overrides Sub OnDrop(ByVal e As System.Windows.DragEventArgs)
        MyBase.OnDrop(e)
        ' If the DataObject contains string data, extract it.
        If e.Data.GetDataPresent(DataFormats.StringFormat) Then
            Dim dataString As String = e.Data.GetData(DataFormats.StringFormat)
    
            ' If the string can be converted into a Brush, 
            ' convert it and apply it to the ellipse.
            Dim converter As New BrushConverter
            If converter.IsValid(dataString) Then
                Dim newFill As 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) Then
                    e.Effects = DragDropEffects.Copy
                Else
                    e.Effects = DragDropEffects.Move
                End If
            End If
        End If
        e.Handled = True
    End Sub
    

    Penimpaan ini OnDrop melakukan tugas-tugas berikut:

    • GetDataPresent Menggunakan metode untuk memeriksa apakah data yang diseret berisi objek string.

    • GetData Menggunakan metode untuk mengekstrak data string jika ada.

    • BrushConverter Menggunakan untuk mencoba mengonversi string menjadi Brush.

    • Jika konversi berhasil, menerapkan kuas ke Fill yang Ellipse menyediakan UI kontrol Lingkaran.

    • Menandai peristiwa sebagai ditangani Drop . Anda harus menandai peristiwa penghilangan sebagai ditangani sehingga elemen lain yang menerima peristiwa ini tahu bahwa kontrol pengguna Lingkaran menanganinya.

  3. Tekan F5 untuk membangun dan menjalankan aplikasi.

  4. Pilih teks green di TextBox.

  5. Seret teks ke kontrol Lingkaran dan letakkan. Lingkaran berubah dari biru ke hijau.

    Convert a string to a brush

  6. Ketik teks green di TextBox.

  7. Pilih teks gre di TextBox.

  8. Seret ke kontrol Lingkaran dan letakkan. Perhatikan bahwa kursor berubah untuk menunjukkan bahwa penurunan diizinkan, tetapi warna Lingkaran tidak berubah karena gre bukan warna yang valid.

  9. Seret dari kontrol Lingkaran hijau dan letakkan pada kontrol Lingkaran biru. Lingkaran berubah dari biru ke hijau. Perhatikan bahwa kursor mana yang ditampilkan tergantung pada apakah TextBox atau Lingkaran adalah sumber seret.

AllowDrop Mengatur properti ke true dan memproses data yang dihilangkan adalah semua yang diperlukan untuk mengaktifkan elemen menjadi target penghilangan. Namun, untuk memberikan pengalaman pengguna yang lebih baik, Anda juga harus menangani DragEnterperistiwa , DragLeave, dan DragOver . Dalam peristiwa ini, Anda dapat melakukan pemeriksaan dan memberikan umpan balik tambahan kepada pengguna sebelum data dihilangkan.

Saat data diseret melalui kontrol pengguna Lingkaran, kontrol harus memberi tahu sumber seret apakah dapat memproses data yang sedang diseret. Jika kontrol tidak tahu cara memproses data, kontrol harus menolak penurunan. Untuk melakukan ini, Anda akan menangani DragOver peristiwa dan mengatur Effects properti .

Untuk memverifikasi bahwa penurunan data diizinkan

  1. Buka Circle.xaml.cs atau Circle.xaml.vb.

  2. Tambahkan penimpaan berikut OnDragOver untuk menyediakan penanganan kelas untuk peristiwa tersebut DragOver .

    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;
    }
    
    Protected Overrides Sub OnDragOver(ByVal e As System.Windows.DragEventArgs)
        MyBase.OnDragOver(e)
        e.Effects = DragDropEffects.None
    
        ' If the DataObject contains string data, extract it.
        If e.Data.GetDataPresent(DataFormats.StringFormat) Then
            Dim dataString As String = e.Data.GetData(DataFormats.StringFormat)
    
            ' If the string can be converted into a Brush, allow copying or moving.
            Dim converter As New BrushConverter
            If converter.IsValid(dataString) Then
                ' 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) Then
                    e.Effects = DragDropEffects.Copy
                Else
                    e.Effects = DragDropEffects.Move
                End If
            End If
        End If
        e.Handled = True
    End Sub
    

    Penimpaan ini OnDragOver melakukan tugas-tugas berikut:

    • Mengatur properti ke EffectsNone.

    • Melakukan pemeriksaan yang sama yang dilakukan dalam OnDrop metode untuk menentukan apakah kontrol pengguna Lingkaran dapat memproses data yang diseret.

    • Jika kontrol pengguna dapat memproses data, atur properti ke EffectsCopy atau Move.

  3. Tekan F5 untuk membangun dan menjalankan aplikasi.

  4. Pilih teks gre di TextBox.

  5. Seret teks ke kontrol Lingkaran. Perhatikan bahwa kursor sekarang berubah untuk menunjukkan bahwa penurunan tidak diizinkan karena gre bukan warna yang valid.

Anda dapat lebih meningkatkan pengalaman pengguna dengan menerapkan pratinjau operasi pengantaran. Untuk kontrol pengguna Lingkaran, Anda akan mengambil OnDragEnter alih metode dan OnDragLeave . Saat data diseret ke kontrol, latar belakang Fill saat ini disimpan dalam variabel tempat penampung. String kemudian dikonversi ke kuas dan diterapkan ke Ellipse yang menyediakan UI Lingkaran. Jika data diseret keluar dari Lingkaran tanpa dihilangkan, nilai asli Fill diterapkan kembali ke Lingkaran.

Untuk mempratinjau efek operasi seret dan letakkan

  1. Buka Circle.xaml.cs atau Circle.xaml.vb.

  2. Di kelas Lingkaran, deklarasikan variabel privat Brush bernama _previousFill dan inisialisasi ke null.

    public partial class Circle : UserControl
    {
        private Brush _previousFill = null;
    
    Public Class Circle
        Private _previousFill As Brush = Nothing
    
  3. Tambahkan penimpaan berikut OnDragEnter untuk menyediakan penanganan kelas untuk peristiwa tersebut DragEnter .

    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;
            }
        }
    }
    
    Protected Overrides Sub OnDragEnter(ByVal e As System.Windows.DragEventArgs)
        MyBase.OnDragEnter(e)
        _previousFill = circleUI.Fill
    
        ' If the DataObject contains string data, extract it.
        If e.Data.GetDataPresent(DataFormats.StringFormat) Then
            Dim dataString As String = e.Data.GetData(DataFormats.StringFormat)
    
            ' If the string can be converted into a Brush, convert it.
            Dim converter As New BrushConverter
            If converter.IsValid(dataString) Then
                Dim newFill As Brush = converter.ConvertFromString(dataString)
                circleUI.Fill = newFill
            End If
        End If
        e.Handled = True
    End Sub
    

    Penimpaan ini OnDragEnter melakukan tugas-tugas berikut:

    • Fill Menyimpan properti dari Ellipse dalam _previousFill variabel.

    • Melakukan pemeriksaan yang sama yang dilakukan dalam OnDrop metode untuk menentukan apakah data dapat dikonversi ke Brush.

    • Jika data dikonversi ke valid Brush, menerapkannya ke Fill dari Ellipse.

  4. Tambahkan penimpaan berikut OnDragLeave untuk menyediakan penanganan kelas untuk peristiwa tersebut DragLeave .

    protected override void OnDragLeave(DragEventArgs e)
    {
        base.OnDragLeave(e);
        // Undo the preview that was applied in OnDragEnter.
        circleUI.Fill = _previousFill;
    }
    
    Protected Overrides Sub OnDragLeave(ByVal e As System.Windows.DragEventArgs)
        MyBase.OnDragLeave(e)
        ' Undo the preview that was applied in OnDragEnter.
        circleUI.Fill = _previousFill
    End Sub
    

    Penimpaan ini OnDragLeave melakukan tugas-tugas berikut:

    • Menerapkan yang Brush disimpan dalam _previousFill variabel ke Fill yang Ellipse menyediakan UI kontrol pengguna Lingkaran.
  5. Tekan F5 untuk membangun dan menjalankan aplikasi.

  6. Pilih teks green di TextBox.

  7. Seret teks ke kontrol Lingkaran tanpa menjatuhkannya. Lingkaran berubah dari biru ke hijau.

    Preview the effects of a drag-and-drop operation

  8. Seret teks menjauh dari kontrol Lingkaran. Lingkaran berubah dari hijau kembali ke biru.

Aktifkan Panel untuk Menerima Data yang Dihilangkan

Di bagian ini, Anda mengaktifkan panel yang menghosting kontrol pengguna Lingkaran untuk bertindak sebagai target penurunan untuk data Lingkaran yang diseret. Anda akan menerapkan kode yang memungkinkan Anda memindahkan Lingkaran dari satu panel ke panel lain, atau membuat salinan kontrol Lingkaran dengan menahan tombol Ctrl saat menyeret dan menjatuhkan Lingkaran.

  1. Buka MainWindow.xaml.

  2. Seperti yang ditunjukkan pada XAML berikut, di setiap StackPanel kontrol, tambahkan handler untuk DragOver peristiwa dan Drop . Beri nama penanganan DragOver aktivitas, panel_DragOver, dan beri nama penanganan Drop aktivitas, panel_Drop.

    Secara default, panel tidak menghilangkan target. Untuk mengaktifkannya, tambahkan properti ke AllowDrop kedua panel dan atur nilai ke true.

    <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. Buka MainWindows.xaml.cs atau MainWindow.xaml.vb.

  4. Tambahkan kode berikut untuk penanganan DragOver aktivitas.

    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;
            }
        }
    }
    
    Private Sub panel_DragOver(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs)
        If e.Data.GetDataPresent("Object") Then
            ' These Effects values are used in the drag source's
            ' GiveFeedback event handler to determine which cursor to display.
            If e.KeyStates = DragDropKeyStates.ControlKey Then
                e.Effects = DragDropEffects.Copy
            Else
                e.Effects = DragDropEffects.Move
            End If
        End If
    End Sub
    

    Penanganan aktivitas ini DragOver melakukan tugas berikut:

    • Memeriksa apakah data yang diseret berisi data "Objek" yang dikemas dalam DataObject kontrol pengguna Lingkaran dan diteruskan dalam panggilan ke DoDragDrop.

    • Jika data "Objek" ada, periksa apakah tombol Ctrl ditekan.

    • Jika tombol Ctrl ditekan, atur properti ke EffectsCopy. Jika tidak, atur properti ke EffectsMove.

  5. Tambahkan kode berikut untuk penanganan Drop aktivitas.

    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;
                    }
                }
            }
        }
    }
    
    Private Sub panel_Drop(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs)
        ' If an element in the panel has already handled the drop,
        ' the panel should not also handle it.
        If e.Handled = False Then
            Dim _panel As Panel = sender
            Dim _element As UIElement = e.Data.GetData("Object")
    
            If _panel IsNot Nothing And _element IsNot Nothing Then
                ' 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.
    
                Dim _parent As Panel = VisualTreeHelper.GetParent(_element)
                If _parent IsNot Nothing Then
                    If e.KeyStates = DragDropKeyStates.ControlKey And _
                        e.AllowedEffects.HasFlag(DragDropEffects.Copy) Then
                        Dim _circle As New Circle(_element)
                        _panel.Children.Add(_circle)
                        ' set the value to return to the DoDragDrop call
                        e.Effects = DragDropEffects.Copy
                    ElseIf e.AllowedEffects.HasFlag(DragDropEffects.Move) Then
                        _parent.Children.Remove(_element)
                        _panel.Children.Add(_element)
                        ' set the value to return to the DoDragDrop call
                        e.Effects = DragDropEffects.Move
                    End If
                End If
            End If
        End If
    End Sub
    

    Penanganan aktivitas ini Drop melakukan tugas berikut:

    • Memeriksa apakah Drop peristiwa telah ditangani. Misalnya, jika Lingkaran dihilangkan di Lingkaran lain yang menangani Drop peristiwa, Anda tidak ingin panel yang berisi Lingkaran juga menanganinya.

    • Drop Jika peristiwa tidak ditangani, periksa apakah tombol Ctrl ditekan.

    • Jika tombol Ctrl ditekan saat Drop terjadi, buat salinan kontrol Lingkaran dan tambahkan ke Children koleksi StackPanel.

    • Jika tombol Ctrl tidak ditekan, memindahkan Lingkaran dari Children kumpulan panel induknya ke Children kumpulan panel tempat tombol tersebut dihilangkan.

    • Effects Mengatur properti untuk memberi tahu DoDragDrop metode apakah operasi pemindahan atau penyalinan dilakukan.

  6. Tekan F5 untuk membangun dan menjalankan aplikasi.

  7. Pilih teks green dari TextBox.

  8. Seret teks ke kontrol Lingkaran dan letakkan.

  9. Seret kontrol Lingkaran dari panel kiri ke panel kanan dan letakkan. Lingkaran dihapus dari Children koleksi panel kiri dan ditambahkan ke koleksi Anak dari panel kanan.

  10. Seret kontrol Lingkaran dari panel yang ada di panel lain dan letakkan saat menekan tombol Ctrl . Lingkaran disalin dan salinan ditambahkan ke Children koleksi panel penerima.

    Dragging a Circle while pressing the CTRL key

Baca juga