Bagikan melalui


Panduan: Mengaktifkan Seret dan Letakkan pada Kontrol Pengguna

Panduan langkah-demi-langkah ini menunjukkan cara membuat kontrol pengguna khusus yang mendukung transfer data drag-and-drop di Windows Presentation Foundation (WPF).

Dalam panduan ini, Anda akan membuat WPF UserControl kustom yang mewakili bentuk lingkaran. Anda akan menerapkan fungsionalitas untuk kontrol guna mengaktifkan transfer data melalui seret dan lepas. Misalnya, jika Anda menyeret dari satu kontrol Lingkaran ke kontrol Lingkaran lainnya, data warna isi akan disalin dari Lingkaran asal ke Lingkaran tujuan. 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 dijatuhkan, sehingga Anda dapat memindahkan atau menyalin Lingkaran dari koleksi 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.

    File Circle.xaml dan kode belakangnya telah ditambahkan ke dalam proyek.

  3. Buka file Circle.xaml.

    File ini akan berisi elemen antarmuka pengguna dari 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 Event Seret Sumber pada Kontrol Pengguna

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

Jika proses menyeret dimulai (tombol mouse ditekan dan mouse dipindahkan), Anda akan mengemas data yang akan ditransfer menjadi bagian dari 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 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
    

    Penggantian ini OnMouseMove melaksanakan 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 lepas. Anda meneruskan tiga parameter berikut ke DoDragDrop metode :

      • dragSource – Referensi ke kontrol ini.

      • data – yang DataObject dibuat dalam kode sebelumnya.

      • allowedEffects – Operasi drag-and-drop 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 atas TextBox, 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.

    Representasi string warna isian dari Lingkaran

Secara default, kursor akan berubah selama operasi seret dan letakkan untuk menunjukkan efek apa yang terjadi pada data tersebut. Anda dapat menyesuaikan respons untuk pengguna dengan menangani event GiveFeedback 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 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
    

    Penggantian ini OnGiveFeedback melaksanakan tugas-tugas berikut:

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

    • Mengatur kursor kustom berdasarkan nilai Effects. Kursor dimaksudkan untuk memberikan umpan balik visual kepada pengguna tentang dampak menjatuhkan 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 disetel sebagai kursor kustom yang Anda tentukan dalam penyesuaian OnGiveFeedback.

    Seret dan letakkan dengan kursor kustom

  5. Pilih teks green dari TextBox.

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

Menerapkan Peristiwa Sasaran Drop di Kontrol Pemakai

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

Untuk mengaktifkan elemen kontrol pengguna menjadi target penjatuhan

  1. Buka file 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 properti AllowDrop diatur ke true dan data dari sumber seret dijatuhkan pada Lingkaran kontrol pengguna. Dalam metode ini, Anda akan memproses data yang dihilangkan dan menerapkan data ke Lingkaran.

Untuk memproses data yang terjatuh

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

  2. Tambahkan penimpaan berikut OnDrop untuk menyediakan penanganan kelas untuk peristiwa 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
    

    Penggantian ini OnDrop melaksanakan tugas-tugas berikut:

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

    • GetData Menggunakan metode untuk mengekstrak data string jika ada.

    • Menggunakan BrushConverter untuk mencoba mengonversi string menjadi Brush.

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

    • Menandai acara Drop sebagai sudah ditangani. Anda harus menandai peristiwa pelepasan sebagai telah ditangani sehingga elemen lain yang menerima peristiwa ini mengetahui bahwa kontrol 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.

    Mengonversi string menjadi kuas

  6. Ketik teks green di TextBox.

  7. Pilih teks gre di TextBox.

  8. Seret objek tersebut ke kontrol Lingkaran dan meletakannya. 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.

Mengatur properti AllowDrop ke true dan memproses data yang dijatuhkan sudah cukup untuk mengaktifkan elemen sebagai target jatuhan. 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 event 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 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
    

    Penggantian ini OnDragOver melaksanakan tugas-tugas berikut:

    • Mengatur properti Effects ke None.

    • Melakukan pemeriksaan yang sama seperti yang dilakukan dalam metode OnDrop untuk menentukan apakah kontrol antarmuka 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 kendali 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 mengganti metode OnDragEnter 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 lepas

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

    Penggantian ini OnDragEnter melaksanakan 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 menjadi bentuk yang valid Brush, data tersebut diterapkan ke bagian Fill dari struktur Ellipse.

  4. Tambahkan penimpaan berikut OnDragLeave untuk menyediakan penanganan kelas untuk peristiwa 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
    

    Penggantian ini OnDragLeave melaksanakan tugas-tugas berikut:

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

  6. Pilih teks green di TextBox.

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

    Pratinjau efek operasi seret dan lepas

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

Aktifkan Panel untuk Menerima Data yang Dijatuhkan

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 AllowDrop ke kedua panel dan atur nilainya menjadi 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 "Object" yang dikemas dalam DataObject oleh kontrol pengguna Circle 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 event Drop telah ditangani. Misalnya, jika Lingkaran dijatuhkan pada Lingkaran lain yang menangani event Drop, 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, membuat sebuah salinan kontrol Lingkaran tersebut dan menambahkannya ke dalam koleksi Children dari StackPanel.

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

    • 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. Tarik kontrol Lingkaran dari panel kiri ke panel kanan dan lepaskan. Lingkaran dihapus dari Children koleksi panel kiri dan ditambahkan ke koleksi Anak dari panel kanan.

  10. Seret kontrol Lingkaran dari panel tempatnya berada ke panel lain dan letakkan sambil menekan tombol Ctrl. Lingkaran disalin dan salinannya ditambahkan ke Children kumpulan panel penerima.

    Menyeret Lingkaran sambil menekan tombol CTRL

Lihat juga