Sdílet prostřednictvím


Návod: Povolení přetahování pomocí myši na uživatelském ovládacím prvku

Tento názorný postup ukazuje, jak vytvořit vlastní uživatelský ovládací prvek, který se může účastnit přenosu dat přetažením ve Windows Presentation Foundation (WPF).

V tomto názorném postupu vytvoříte vlastní WPF UserControl , který představuje obrazec kruhu. Na ovládacím prvku implementujete funkce pro povolení přenosu dat přetažením. Pokud například přetáhnete z jednoho ovládacího prvku Kruh do druhého, zkopírují se barevná data výplně ze zdrojového kruhu do cíle. Pokud přetáhnete ovládací prvek Kruh do objektu TextBox, řetězec reprezentace barvy výplně se zkopíruje do TextBox. Vytvoříte také malou aplikaci, která obsahuje dva ovládací prvky panelu a funkci TextBox přetažení. Napíšete kód, který umožňuje panelům zpracovávat vynechaná data Circle, což vám umožní přesunout nebo zkopírovat kruhy z podřízené kolekce jednoho panelu na druhý.

Tento návod znázorňuje následující úlohy:

  • Vytvořte vlastní uživatelský ovládací prvek.

  • Povolte uživatelskému ovládacímu prvku, aby byl zdrojem přetažení.

  • Povolte, aby uživatelský ovládací prvek byl cílem přetažení.

  • Umožňuje panelu přijímat data vyřazená z uživatelského ovládacího prvku.

Předpoklady

K dokončení tohoto návodu potřebujete Visual Studio.

Vytvoření projektu aplikace

V této části vytvoříte infrastrukturu aplikace, která obsahuje hlavní stránku se dvěma panely a .TextBox

  1. Vytvořte nový projekt aplikace WPF v jazyce Visual Basic nebo Visual C# s názvem DragDropExample. Další informace naleznete v tématu Návod: Moje první desktopová aplikace WPF.

  2. Otevřete MainWindow.xaml.

  3. Mezi levou a pravou Grid značku přidejte následující kód.

    Tento kód vytvoří uživatelské rozhraní pro testovací aplikaci.

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

Přidání nového uživatelského ovládacího prvku do projektu

V této části přidáte do projektu nový uživatelský ovládací prvek.

  1. V nabídce Projekt vyberte Přidat uživatelský ovládací prvek.

  2. V dialogovém okně Přidat novou položku změňte název na Circle.xamla klepněte na tlačítko Přidat.

    Do projektu se přidá Circle.xaml a jeho kód za kódem.

  3. Otevřete Circle.xaml.

    Tento soubor bude obsahovat prvky uživatelského rozhraní uživatelského ovládacího prvku.

  4. Přidáním následujícího kódu do kořenového adresáře Grid vytvořte jednoduchý uživatelský ovládací prvek, který má modrý kruh jako uživatelské rozhraní.

    <Ellipse x:Name="circleUI" 
             Height="100" Width="100"
             Fill="Blue" />
    
  5. Otevřete Circle.xaml.cs nebo Circle.xaml.vb.

  6. V jazyce C# přidejte následující kód za konstruktor bez parametrů, který vytvoří konstruktor kopírování. V jazyce Visual Basic přidejte následující kód pro vytvoření konstruktoru bez parametrů i konstruktoru kopírování.

    Chcete-li povolit kopírování uživatelského ovládacího prvku, přidáte do souboru kódu metodu konstruktoru kopírování. Ve zjednodušeném uživatelském ovládacím prvku Circle zkopírujete pouze výplň a velikost uživatelského ovládacího prvku.

    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
    

Přidání uživatelského ovládacího prvku do hlavního okna

  1. Otevřete MainWindow.xaml.

  2. Přidejte následující kód XAML do počáteční Window značky a vytvořte odkaz na obor názvů XML pro aktuální aplikaci.

    xmlns:local="clr-namespace:DragDropExample"
    
  3. V prvním StackPanelkroku přidejte následující XAML pro vytvoření dvou instancí uživatelského ovládacího prvku Circle na prvním panelu.

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

    Úplný kód XAML pro panel vypadá následovně.

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

Implementace zdrojových událostí přetažení v uživatelském ovládacím prvku

V této části přepíšete metodu OnMouseMove a zahájíte operaci přetažení.

Pokud se spustí přetažení (stisknete tlačítko myši a přesune se myš), zabalíte data, která se mají přenést do objektu DataObject. V tomto případě bude ovládací prvek Circle zabalovat tři datové položky; řetězcové znázornění barvy výplně, dvojité znázornění jeho výšky a kopie sebe sama.

Zahájení operace přetažení

  1. Otevřete Circle.xaml.cs nebo Circle.xaml.vb.

  2. Přidejte následující OnMouseMove přepsání, které zajistí zpracování tříd pro MouseMove událost.

    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
    

    Toto OnMouseMove přepsání provádí následující úlohy:

    • Zkontroluje, jestli je levé tlačítko myši při přesouvání stisknuto.

    • Zabalí data Circle do .DataObject V tomto případě ovládací prvek Circle zabalí tři datové položky; řetězcové znázornění barvy výplně, dvojité znázornění jeho výšky a kopie sebe sama.

    • Zavolá statickou DragDrop.DoDragDrop metodu, která zahájí operaci přetažení. Metodě předáte následující tři parametry DoDragDrop :

      • dragSource – Odkaz na tento ovládací prvek.

      • data – Vytvořeno DataObject v předchozím kódu.

      • allowedEffects – Povolené operace přetažení, které jsou Copy nebo Move.

  3. Stiskněte F5, aby se aplikace sestavila a spustila.

  4. Klikněte na jeden z ovládacích prvků Kruh a přetáhněte ho přes panely, druhý kruh a TextBoxtlačítko . Když ho TextBoxpřetáhnete, kurzor se změní tak, aby označil přesunutí.

  5. Při přetahování kruhu přes klávesu TextBox Ctrl. Všimněte si, jak se kurzor změní, aby označí kopii.

  6. Přetáhněte kruh na tlačítko TextBox. Řetězcová reprezentace barvy výplně kruhu je připojena TextBoxk .

    String representation of Circle's fill color

Ve výchozím nastavení se kurzor během operace přetažení změní, aby indikovaly, jaký efekt budou mít data vyřazení. Zpětnou vazbu, kterou uživatel poskytl, můžete přizpůsobit zpracováním GiveFeedback události a nastavením jiného kurzoru.

Pošlete uživateli zpětnou vazbu

  1. Otevřete Circle.xaml.cs nebo Circle.xaml.vb.

  2. Přidejte následující OnGiveFeedback přepsání, které zajistí zpracování tříd pro GiveFeedback událost.

    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
    

    Toto OnGiveFeedback přepsání provádí následující úlohy:

    • Zkontroluje Effects hodnoty, které jsou nastaveny v obslužné rutině DragOver události cíle drop.

    • Nastaví vlastní kurzor na Effects základě hodnoty. Kurzor je určený k tomu, aby uživateli poskytl vizuální zpětnou vazbu o tom, jaký vliv bude mít vyřazení dat.

  3. Stiskněte F5, aby se aplikace sestavila a spustila.

  4. Přetáhněte jeden z ovládacích prvků Kruh přes panely, druhý kruh a TextBoxtlačítko . Všimněte si, že kurzory jsou teď vlastními kurzory, které jste zadali v přepsání OnGiveFeedback .

    Drag and drop with custom cursors

  5. Vyberte text green z pole TextBox.

  6. green Přetáhněte text do ovládacího prvku Kruh. Všimněte si, že se zobrazí výchozí kurzory, které označují účinky operace přetažení myší. Kurzor zpětné vazby je vždy nastaven zdrojem přetažení.

Implementace cílových událostí přetažení v uživatelském ovládacím prvku

V této části určíte, že uživatelský ovládací prvek je cíl pro vyřazení, přepíše metody, které umožňují, aby uživatelský ovládací prvek byl cílem přetažení, a zpracovávat data, která jsou na něm vyřazena.

Povolení, aby uživatelský ovládací prvek byl cílem pro vyřazení

  1. Otevřete Circle.xaml.

  2. Do počáteční UserControl značky přidejte AllowDrop vlastnost a nastavte ji na 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">
    

Metoda OnDrop je volána, když AllowDrop je vlastnost nastavena na true a data ze zdroje přetažení je vynechána v uživatelském ovládacím prvku Circle. V této metodě zpracujete data, která byla vyřazena, a použijete je na kruh.

Zpracování vyřazených dat

  1. Otevřete Circle.xaml.cs nebo Circle.xaml.vb.

  2. Přidejte následující OnDrop přepsání, které zajistí zpracování tříd pro Drop událost.

    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
    

    Toto OnDrop přepsání provádí následující úlohy:

    • GetDataPresent Pomocí metody zkontroluje, jestli přetažená data obsahují objekt řetězce.

    • Používá metodu GetData k extrahování řetězcových dat, pokud jsou k dispozici.

    • BrushConverter Používá k pokusu o převod řetězce na Brush.

    • Pokud je převod úspěšný, použije štětec na FillEllipse ovládací prvek Kruh, který poskytuje uživatelské rozhraní ovládacího prvku Circle.

    • Drop Označí událost jako zpracovanou. Událost přetažení byste měli označit jako zpracovánou, aby ostatní prvky, které tuto událost obdrží, věděli, že uživatelský ovládací prvek Circle ho zpracoval.

  3. Stiskněte F5, aby se aplikace sestavila a spustila.

  4. Vyberte text green v sadě TextBox.

  5. Přetáhněte text do ovládacího prvku Kruh a přetáhněte ho. Kruh se změní z modré na zelenou.

    Convert a string to a brush

  6. Zadejte text green do pole TextBox.

  7. Vyberte text gre v sadě TextBox.

  8. Přetáhněte ho do ovládacího prvku Kruh a přesuňte ho. Všimněte si, že kurzor se změní tak, aby značil, že je povolené přetažení, ale barva kruhu se nezmění, protože gre není platná barva.

  9. Přetáhněte z zeleného ovládacího prvku Kruh a přetáhněte ho do modrého ovládacího prvku Kruh. Kruh se změní z modré na zelenou. Všimněte si, že zobrazený kurzor závisí na tom, zda TextBox je zdrojem přetažení kruh nebo kruh.

AllowDrop Nastavení vlastnosti na true a zpracování vynechaných dat je vše, co je nutné k povolení elementu, aby byl cíl přetažení. Chcete-li však zajistit lepší uživatelské prostředí, měli byste také zpracovat DragEnter, DragLeavea DragOver události. V těchto událostech můžete před vyřazením dat provést kontroly a poskytnout uživateli další zpětnou vazbu.

Když jsou data přetažena přes uživatelský ovládací prvek Circle, měl by ovládací prvek upozornit zdroj přetažení, zda může zpracovávat data, která jsou přetažena. Pokud ovládací prvek neví, jak zpracovat data, měl by odmítnout pokles. Provedete to tak, že zpracujete DragOver událost a nastavíte Effects vlastnost.

Ověření, že je povolené vyřazení dat

  1. Otevřete Circle.xaml.cs nebo Circle.xaml.vb.

  2. Přidejte následující OnDragOver přepsání, které zajistí zpracování tříd pro DragOver událost.

    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
    

    Toto OnDragOver přepsání provádí následující úlohy:

    • Effects Nastaví vlastnost na None.

    • Provede stejné kontroly, které jsou provedeny v OnDrop metodě k určení, zda uživatelský ovládací prvek Circle může zpracovat přetažená data.

    • Pokud uživatelský ovládací prvek může zpracovávat data, nastaví Effects vlastnost na Copy nebo Move.

  3. Stiskněte F5, aby se aplikace sestavila a spustila.

  4. Vyberte text gre v sadě TextBox.

  5. Přetáhněte text do ovládacího prvku Kruh. Všimněte si, že kurzor se teď změní tak, aby značil, že rozevírací seznam není povolený, protože gre není platná barva.

Uživatelské prostředí můžete dále vylepšit použitím náhledu operace vyřazení. U uživatelského ovládacího prvku Circle přepíšete OnDragEnter metody a OnDragLeave metody. Když jsou data přetažena přes ovládací prvek, aktuální pozadí Fill se uloží do zástupné proměnné. Řetězec se pak převede na štětec a použije se na Ellipse uživatelské rozhraní Kruhu. Pokud jsou data přetažena z kruhu bez vyřazení, původní Fill hodnota se znovu použije u kruhu.

Zobrazení náhledu efektů operace přetažení myší

  1. Otevřete Circle.xaml.cs nebo Circle.xaml.vb.

  2. Ve třídě Circle deklarujte privátní Brush proměnnou s názvem _previousFill a inicializujete ji na null.

    public partial class Circle : UserControl
    {
        private Brush _previousFill = null;
    
    Public Class Circle
        Private _previousFill As Brush = Nothing
    
  3. Přidejte následující OnDragEnter přepsání, které zajistí zpracování tříd pro DragEnter událost.

    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
    

    Toto OnDragEnter přepsání provádí následující úlohy:

    • Uloží Fill vlastnost Ellipse proměnné _previousFill .

    • Provede stejné kontroly, které jsou provedeny v OnDrop metodě určit, zda lze data převést na Brush.

    • Pokud jsou data převedena na platnou Brush, použije je na FillEllipse

  4. Přidejte následující OnDragLeave přepsání, které zajistí zpracování tříd pro DragLeave událost.

    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
    

    Toto OnDragLeave přepsání provádí následující úlohy:

    • Použije uloženou Brush v _previousFill proměnné na FillEllipse uživatelské rozhraní uživatelského ovládacího prvku Circle.
  5. Stiskněte F5, aby se aplikace sestavila a spustila.

  6. Vyberte text green v sadě TextBox.

  7. Přetáhněte text přes ovládací prvek Kruh, aniž byste ho přetáhli. Kruh se změní z modré na zelenou.

    Preview the effects of a drag-and-drop operation

  8. Přetáhněte text mimo ovládací prvek Kruh. Kruh se změní ze zelené na modrou.

Povolení panelu pro příjem vyřazených dat

V této části povolíte panely, které hostují uživatelské ovládací prvky Circle, aby fungovaly jako cíle přetažení pro přetažená data Kruhu. Implementujete kód, který vám umožní přesunout kruh z jednoho panelu do druhého nebo vytvořit kopii ovládacího prvku Kruh podržením klávesy Ctrl a přetažením kruhu.

  1. Otevřete MainWindow.xaml.

  2. Jak je znázorněno v následujícím kódu XAML, přidejte v každém ovládacím StackPanel prvku obslužné rutiny pro události DragOver a Drop události. Pojmenujte obslužnou rutinu DragOverpanel_DragOverudálosti a pojmenujte obslužnou rutinu Droppanel_Dropudálosti .

    Ve výchozím nastavení nejsou panely cíle. Chcete-li je povolit, přidejte AllowDrop vlastnost na oba panely a nastavte hodnotu na 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. Otevřete MainWindows.xaml.cs nebo MainWindow.xaml.vb.

  4. Přidejte následující kód pro obslužnou rutinu DragOver události.

    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
    

    Tato DragOver obslužná rutina události provádí následující úlohy:

    • Kontroluje, zda přetažená data obsahují data "Object", která byla zabalena v DataObject uživatelském ovládacím prvku Circle a předána DoDragDropvolání .

    • Pokud jsou k dispozici data "Objekt", zkontroluje, zda je stisknuta klávesa Ctrl .

    • Pokud je stisknuta klávesa Ctrl , nastaví Effects vlastnost na Copyhodnotu . V opačném případě nastavte Effects vlastnost na Movehodnotu .

  5. Přidejte následující kód pro obslužnou rutinu Drop události.

    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
    

    Tato Drop obslužná rutina události provádí následující úlohy:

    • Zkontroluje, jestli Drop už byla událost zpracována. Pokud je například kruh vyřazen do jiného kruhu, který zpracovává Drop událost, nechcete, aby panel obsahující kruh také zpracovával.

    • Drop Pokud se událost nezpracuje, zkontroluje, jestli je stisknutá klávesa Ctrl.

    • Pokud se stiskne klávesa Ctrl , Drop vytvoří kopii ovládacího prvku Circle a přidá ji do Children kolekce objektu StackPanel.

    • Pokud není stisknutá klávesa Ctrl , přesune kruh z Children kolekce nadřazeného panelu do Children kolekce panelu, na který byl vyřazen.

    • Effects Nastaví vlastnost tak, aby upozorňovat metoduDoDragDrop, zda byla provedena operace přesunutí nebo kopírování.

  6. Stiskněte F5, aby se aplikace sestavila a spustila.

  7. Vyberte text green z pole TextBox.

  8. Přetáhněte text přes ovládací prvek Kruh a přetáhněte ho.

  9. Přetáhněte ovládací prvek Kruh z levého panelu do pravého panelu a přetáhněte ho. Kruh se odebere z Children kolekce levého panelu a přidá se do podřízené kolekce pravého panelu.

  10. Přetáhněte ovládací prvek Kruh z panelu, který je na druhém panelu, a podržte stisknutou klávesu Ctrl . Kruh se zkopíruje a kopie se přidá do Children kolekce přijímajícího panelu.

    Dragging a Circle while pressing the CTRL key

Viz také