如果想要建立控件事件Drag & Drop 的结果, 从一个控件中的某一项拖动到另一个控件中,使用VB.NET & C # 的实例如下。
XAML - Window1.xaml
______________________________
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SampleDragDrop" Height="300" Width="300"
>
<Window.Resources>
<XmlDataProvider x:Key="MyData">
<x:XData>
<Sections xmlns="" Title="Library Favorites">
<Section Name=".NET Development">
<Article Name="Articles and Overview" />
<Article Name=".NET Performance" />
<Article Name="Windows Vista" />
<Article Name="XML and the .NET Framework" />
</Section>
</Sections>
</x:XData>
</XmlDataProvider>
<DataTemplate x:Key="ArticleTemplate">
<TextBlock FontSize="10pt" Text="{Binding XPath=@Name}" />
</DataTemplate>
</Window.Resources>
<DockPanel>
<Border DockPanel.Dock="Top" BorderBrush="DarkGray" BorderThickness="2" Padding="4">
<TextBlock FontSize="8pt" FontFamily="Tahoma" TextWrapping="Wrap">
<Bold>
Drag Sample
</Bold>
<LineBreak />
<Run>
This sample demonstrates using a DataObject for dragging "pure" data.
</Run>
</TextBlock>
</Border>
<ListBox Name="myListBox" AllowDrop="True"
ItemsSource="{Binding Source={StaticResource MyData}, XPath=/Sections/Section/Article}"
ItemTemplate="{StaticResource ArticleTemplate}">
<ListBox.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0" />
<GradientStop Color="DarkBlue" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</ListBox.Background>
</ListBox>
</DockPanel>
</Window>
______________________________
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SampleDragDrop" Height="300" Width="300"
>
<Window.Resources>
<XmlDataProvider x:Key="MyData">
<x:XData>
<Sections xmlns="" Title="Library Favorites">
<Section Name=".NET Development">
<Article Name="Articles and Overview" />
<Article Name=".NET Performance" />
<Article Name="Windows Vista" />
<Article Name="XML and the .NET Framework" />
</Section>
</Sections>
</x:XData>
</XmlDataProvider>
<DataTemplate x:Key="ArticleTemplate">
<TextBlock FontSize="10pt" Text="{Binding XPath=@Name}" />
</DataTemplate>
</Window.Resources>
<DockPanel>
<Border DockPanel.Dock="Top" BorderBrush="DarkGray" BorderThickness="2" Padding="4">
<TextBlock FontSize="8pt" FontFamily="Tahoma" TextWrapping="Wrap">
<Bold>
Drag Sample
</Bold>
<LineBreak />
<Run>
This sample demonstrates using a DataObject for dragging "pure" data.
</Run>
</TextBlock>
</Border>
<ListBox Name="myListBox" AllowDrop="True"
ItemsSource="{Binding Source={StaticResource MyData}, XPath=/Sections/Section/Article}"
ItemTemplate="{StaticResource ArticleTemplate}">
<ListBox.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0" />
<GradientStop Color="DarkBlue" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</ListBox.Background>
</ListBox>
</DockPanel>
</Window>
后台代码 C# - Window1.xaml.cs
public partial class Window1 : Window
{
private Point m_StartPoint;
private bool m_IsDown;
private System.Xml.XmlElement m_OriginalElement;
private DropPreviewAdorner m_OverlayElement;
private System.Xml.XmlElement m_RemoteElement;
private static DataFormat m_MyFormat = DataFormats.GetDataFormat( "My Love-ly Format" );
public Window1()
{
InitializeComponent();
}
protected override void OnInitialized( EventArgs e )
{
base.OnInitialized( e );
myListBox.PreviewMouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler( MyCanvas_PreviewMouseLeftButtonDown );
myListBox.PreviewMouseMove += new System.Windows.Input.MouseEventHandler( MyCanvas_PreviewMouseMove );
myListBox.PreviewDragOver += new DragEventHandler( MyCanvas_PreviewDragOver );
myListBox.PreviewDrop += new DragEventHandler( MyCanvas_PreviewDrop );
myListBox.PreviewDragEnter += new DragEventHandler( MyCanvas_PreviewDragEnter );
myListBox.PreviewDragLeave += new DragEventHandler( MyCanvas_PreviewDragLeave );
}
private void MyCanvas_PreviewMouseLeftButtonDown( object sender, System.Windows.Input.MouseButtonEventArgs e )
{
m_OriginalElement = GetElementFromPoint( myListBox, e.GetPosition( myListBox ) );
if ( m_OriginalElement == null )
{
return;
}
m_IsDown = true;
m_StartPoint = e.GetPosition( myListBox );
}
private System.Xml.XmlElement GetElementFromPoint( ListBox box, Point point )
{
UIElement element = (UIElement)box.InputHitTest( point );
while ( true )
{
if ( element == box )
{
return null;
}
object item = box.ItemContainerGenerator.ItemFromContainer( element );
bool itemFound = !( item.Equals( DependencyProperty.UnsetValue ) );
if ( itemFound )
{
return item as System.Xml.XmlElement;
}
element = (UIElement)VisualTreeHelper.GetParent( element );
}
}
private void MyCanvas_PreviewMouseMove( object sender, System.Windows.Input.MouseEventArgs e )
{
if ( m_IsDown )
{
if ( Math.Abs( e.GetPosition( myListBox ).X - m_StartPoint.X ) > SystemParameters.MinimumHorizontalDragDistance && Math.Abs( e.GetPosition( myListBox ).Y - m_StartPoint.Y ) > SystemParameters.MinimumVerticalDragDistance )
{
DragStarted();
}
}
}
private void DragStarted()
{
m_IsDown = false;
string serializedObject = m_OriginalElement.OuterXml;
DataObject data = new DataObject();
data.SetData( m_MyFormat.Name, serializedObject );
DragDropEffects effects = DragDrop.DoDragDrop( myListBox, data, DragDropEffects.Copy | DragDropEffects.Move );
if ( effects == DragDropEffects.Move )
{
// Remove the element.
m_OriginalElement.ParentNode.RemoveChild( m_OriginalElement );
m_OriginalElement = null;
}
}
private void DragMoved()
{
Point currentPosition = System.Windows.Input.Mouse.GetPosition( myListBox );
m_OverlayElement.LeftOffset = currentPosition.X - m_StartPoint.X;
m_OverlayElement.TopOffset = currentPosition.Y - m_StartPoint.Y;
}
private void MyCanvas_PreviewDragOver( object sender, System.Windows.DragEventArgs e )
{
if ( !( UpdateEffects( e ) ) )
{
return;
}
Point currentPosition = (Point) e.GetPosition( (IInputElement) this.Content );
m_OverlayElement.LeftOffset = currentPosition.X;
m_OverlayElement.TopOffset = currentPosition.Y;
e.Handled = true;
}
private void MyCanvas_PreviewDrop( object sender, System.Windows.DragEventArgs e )
{
if ( !( UpdateEffects( e ) ) )
{
return;
}
XmlDataProvider dataProvider = (XmlDataProvider) FindResource( "MyData" );
System.Xml.XmlDocument document = dataProvider.Document;
System.Xml.XmlElement node = (System.Xml.XmlElement) dataProvider.Document.ImportNode( m_RemoteElement, true );
dataProvider.Document.GetElementsByTagName( "Section" )[0].AppendChild(node);
AdornerLayer.GetAdornerLayer( (System.Windows.Media.Visual) this.Content ).Remove( m_OverlayElement );
m_RemoteElement = null;
m_OverlayElement = null;
e.Handled = true;
}
private void MyCanvas_PreviewDragEnter( object sender, System.Windows.DragEventArgs e )
{
if ( !( UpdateEffects( e ) ) )
{
return;
}
string serializedObject = (string) e.Data.GetData( m_MyFormat.Name );
System.Xml.XmlDocument document = new System.Xml.XmlDocument();
document.LoadXml( serializedObject );
m_RemoteElement = document.DocumentElement;
ContentPresenter presenter = new ContentPresenter();
presenter.Content = m_RemoteElement;
presenter.ContentTemplate = myListBox.ItemTemplate;
AdornerLayer layer;
m_OverlayElement = new DropPreviewAdorner( (UIElement)this.Content, presenter );
layer = AdornerLayer.GetAdornerLayer( (System.Windows.Media.Visual) this.Content );
layer.Add( m_OverlayElement );
e.Handled = true;
}
private void MyCanvas_PreviewDragLeave( object sender, System.Windows.DragEventArgs e )
{
if ( m_OverlayElement == null )
{
return;
}
AdornerLayer.GetAdornerLayer( ( System.Windows.Media.Visual ) this.Content ).Remove( m_OverlayElement );
m_OverlayElement = null;
m_RemoteElement = null;
e.Handled = true;
}
private bool UpdateEffects( System.Windows.DragEventArgs e )
{
if ( !( e.Data.GetDataPresent( m_MyFormat.Name ) ) )
{
e.Effects = DragDropEffects.None;
return false;
}
if ( ( e.AllowedEffects & DragDropEffects.Copy ) == 0 && ( e.AllowedEffects & DragDropEffects.Move ) == 0 )
{
e.Effects = DragDropEffects.None;
return false;
}
if ( ( e.AllowedEffects & DragDropEffects.Copy ) != 0 && ( e.AllowedEffects & DragDropEffects.Move ) != 0 )
{
if ( ( e.KeyStates & DragDropKeyStates.ControlKey ) != 0 )
{
e.Effects = DragDropEffects.Copy;
}
else
{
e.Effects = DragDropEffects.Move;
}
}
else
{
e.Effects = e.AllowedEffects & (( DragDropEffects.Copy | DragDropEffects.Move ) );
}
return true;
}
Adorner Class
{
private Point m_StartPoint;
private bool m_IsDown;
private System.Xml.XmlElement m_OriginalElement;
private DropPreviewAdorner m_OverlayElement;
private System.Xml.XmlElement m_RemoteElement;
private static DataFormat m_MyFormat = DataFormats.GetDataFormat( "My Love-ly Format" );
public Window1()
{
InitializeComponent();
}
protected override void OnInitialized( EventArgs e )
{
base.OnInitialized( e );
myListBox.PreviewMouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler( MyCanvas_PreviewMouseLeftButtonDown );
myListBox.PreviewMouseMove += new System.Windows.Input.MouseEventHandler( MyCanvas_PreviewMouseMove );
myListBox.PreviewDragOver += new DragEventHandler( MyCanvas_PreviewDragOver );
myListBox.PreviewDrop += new DragEventHandler( MyCanvas_PreviewDrop );
myListBox.PreviewDragEnter += new DragEventHandler( MyCanvas_PreviewDragEnter );
myListBox.PreviewDragLeave += new DragEventHandler( MyCanvas_PreviewDragLeave );
}
private void MyCanvas_PreviewMouseLeftButtonDown( object sender, System.Windows.Input.MouseButtonEventArgs e )
{
m_OriginalElement = GetElementFromPoint( myListBox, e.GetPosition( myListBox ) );
if ( m_OriginalElement == null )
{
return;
}
m_IsDown = true;
m_StartPoint = e.GetPosition( myListBox );
}
private System.Xml.XmlElement GetElementFromPoint( ListBox box, Point point )
{
UIElement element = (UIElement)box.InputHitTest( point );
while ( true )
{
if ( element == box )
{
return null;
}
object item = box.ItemContainerGenerator.ItemFromContainer( element );
bool itemFound = !( item.Equals( DependencyProperty.UnsetValue ) );
if ( itemFound )
{
return item as System.Xml.XmlElement;
}
element = (UIElement)VisualTreeHelper.GetParent( element );
}
}
private void MyCanvas_PreviewMouseMove( object sender, System.Windows.Input.MouseEventArgs e )
{
if ( m_IsDown )
{
if ( Math.Abs( e.GetPosition( myListBox ).X - m_StartPoint.X ) > SystemParameters.MinimumHorizontalDragDistance && Math.Abs( e.GetPosition( myListBox ).Y - m_StartPoint.Y ) > SystemParameters.MinimumVerticalDragDistance )
{
DragStarted();
}
}
}
private void DragStarted()
{
m_IsDown = false;
string serializedObject = m_OriginalElement.OuterXml;
DataObject data = new DataObject();
data.SetData( m_MyFormat.Name, serializedObject );
DragDropEffects effects = DragDrop.DoDragDrop( myListBox, data, DragDropEffects.Copy | DragDropEffects.Move );
if ( effects == DragDropEffects.Move )
{
// Remove the element.
m_OriginalElement.ParentNode.RemoveChild( m_OriginalElement );
m_OriginalElement = null;
}
}
private void DragMoved()
{
Point currentPosition = System.Windows.Input.Mouse.GetPosition( myListBox );
m_OverlayElement.LeftOffset = currentPosition.X - m_StartPoint.X;
m_OverlayElement.TopOffset = currentPosition.Y - m_StartPoint.Y;
}
private void MyCanvas_PreviewDragOver( object sender, System.Windows.DragEventArgs e )
{
if ( !( UpdateEffects( e ) ) )
{
return;
}
Point currentPosition = (Point) e.GetPosition( (IInputElement) this.Content );
m_OverlayElement.LeftOffset = currentPosition.X;
m_OverlayElement.TopOffset = currentPosition.Y;
e.Handled = true;
}
private void MyCanvas_PreviewDrop( object sender, System.Windows.DragEventArgs e )
{
if ( !( UpdateEffects( e ) ) )
{
return;
}
XmlDataProvider dataProvider = (XmlDataProvider) FindResource( "MyData" );
System.Xml.XmlDocument document = dataProvider.Document;
System.Xml.XmlElement node = (System.Xml.XmlElement) dataProvider.Document.ImportNode( m_RemoteElement, true );
dataProvider.Document.GetElementsByTagName( "Section" )[0].AppendChild(node);
AdornerLayer.GetAdornerLayer( (System.Windows.Media.Visual) this.Content ).Remove( m_OverlayElement );
m_RemoteElement = null;
m_OverlayElement = null;
e.Handled = true;
}
private void MyCanvas_PreviewDragEnter( object sender, System.Windows.DragEventArgs e )
{
if ( !( UpdateEffects( e ) ) )
{
return;
}
string serializedObject = (string) e.Data.GetData( m_MyFormat.Name );
System.Xml.XmlDocument document = new System.Xml.XmlDocument();
document.LoadXml( serializedObject );
m_RemoteElement = document.DocumentElement;
ContentPresenter presenter = new ContentPresenter();
presenter.Content = m_RemoteElement;
presenter.ContentTemplate = myListBox.ItemTemplate;
AdornerLayer layer;
m_OverlayElement = new DropPreviewAdorner( (UIElement)this.Content, presenter );
layer = AdornerLayer.GetAdornerLayer( (System.Windows.Media.Visual) this.Content );
layer.Add( m_OverlayElement );
e.Handled = true;
}
private void MyCanvas_PreviewDragLeave( object sender, System.Windows.DragEventArgs e )
{
if ( m_OverlayElement == null )
{
return;
}
AdornerLayer.GetAdornerLayer( ( System.Windows.Media.Visual ) this.Content ).Remove( m_OverlayElement );
m_OverlayElement = null;
m_RemoteElement = null;
e.Handled = true;
}
private bool UpdateEffects( System.Windows.DragEventArgs e )
{
if ( !( e.Data.GetDataPresent( m_MyFormat.Name ) ) )
{
e.Effects = DragDropEffects.None;
return false;
}
if ( ( e.AllowedEffects & DragDropEffects.Copy ) == 0 && ( e.AllowedEffects & DragDropEffects.Move ) == 0 )
{
e.Effects = DragDropEffects.None;
return false;
}
if ( ( e.AllowedEffects & DragDropEffects.Copy ) != 0 && ( e.AllowedEffects & DragDropEffects.Move ) != 0 )
{
if ( ( e.KeyStates & DragDropKeyStates.ControlKey ) != 0 )
{
e.Effects = DragDropEffects.Copy;
}
else
{
e.Effects = DragDropEffects.Move;
}
}
else
{
e.Effects = e.AllowedEffects & (( DragDropEffects.Copy | DragDropEffects.Move ) );
}
return true;
}
Adorner Class
后台代码 VB.NET - Window1.xaml.vb
Partial Public Class Window1
Inherits Window
Class DropPreviewAdorner
Inherits Adorner
Public Sub New(ByVal adornedElement As UIElement, _
ByVal adorningElement As UIElement)
MyBase.New(adornedElement)
Dim brush As VisualBrush = New VisualBrush(adorningElement)
m_Child = New Rectangle()
m_Child.Width = adorningElement.RenderSize.Width
m_Child.Height = adorningElement.RenderSize.Height
m_Child.Fill = brush
m_Child.IsHitTestVisible = False
Dim animation As System.Windows.Media.Animation.DoubleAnimation
animation = New System.Windows.Media.Animation.DoubleAnimation(0.3, 1, New Duration(TimeSpan.FromSeconds(1)))
animation.AutoReverse = True
animation.RepeatBehavior = System.Windows.Media.Animation.RepeatBehavior.Forever
brush.BeginAnimation(System.Windows.Media.Brush.OpacityProperty, animation)
End Sub
' Adding some basic fields to help us keep track of where we are and what we render
Private m_Child As Rectangle
Private m_LeftOffset As Double
Private m_TopOffset As Double
Protected Overrides Function MeasureOverride(ByVal constraint As System.Windows.Size) As System.Windows.Size
m_Child.Measure(constraint)
Return m_Child.DesiredSize
End Function
Protected Overrides Function ArrangeOverride(ByVal finalSize As System.Windows.Size) As System.Windows.Size
m_Child.Arrange(New Rect(finalSize))
Return finalSize
End Function
Protected Overrides Function GetVisualChild(ByVal index As Integer) As System.Windows.Media.Visual
Return m_Child
End Function
Protected Overrides ReadOnly Property VisualChildrenCount() As Integer
Get
Return 1
End Get
End Property
Public Property LeftOffset() As Double
Get
Return m_LeftOffset
End Get
Set(ByVal value As Double)
m_LeftOffset = value
UpdatePosition()
End Set
End Property
Public Property TopOffset() As Double
Get
Return m_TopOffset
End Get
Set(ByVal value As Double)
m_TopOffset = value
UpdatePosition()
End Set
End Property
Private Sub UpdatePosition()
Dim adornerLayer As AdornerLayer = Me.Parent
If Not adornerLayer Is Nothing Then
adornerLayer.Update(AdornedElement)
End If
End Sub
Public Overrides Function GetDesiredTransform(ByVal transform As System.Windows.Media.GeneralTransform) As System.Windows.Media.GeneralTransform
Dim result As GeneralTransformGroup = New GeneralTransformGroup()
result.Children.Add(MyBase.GetDesiredTransform(transform))
result.Children.Add(New TranslateTransform(LeftOffset, TopOffset))
Return result
End Function
End Class
Private m_StartPoint As Point ' Where did the mouse start off from?
Private m_IsDown As Boolean ' Is the mouse down right now?
Private m_OriginalElement As System.Xml.XmlElement ' What is it that we're dragging?
Private m_OverlayElement As DropPreviewAdorner ' What is it that we're using to show
Private m_RemoteElement As System.Xml.XmlElement
Private Shared m_MyFormat As DataFormat = DataFormats.GetDataFormat("My Love-ly Format")
Public Sub New()
InitializeComponent()
End Sub
Private Sub myListBox_PreviewMouseLeftButtonDown(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles myListBox.PreviewMouseLeftButtonDown
m_OriginalElement = GetElementFromPoint(myListBox, e.GetPosition(myListBox))
If m_OriginalElement Is Nothing Then Exit Sub
m_IsDown = True
m_StartPoint = e.GetPosition(myListBox)
End Sub
Private Function GetElementFromPoint(ByVal box As ListBox, ByVal point As Point) As System.Xml.XmlElement
Dim element As UIElement = box.InputHitTest(point)
While True
If element Is box Then Return Nothing
Dim item As Object = box.ItemContainerGenerator.ItemFromContainer(element)
Dim itemFound As Boolean = Not item.Equals(DependencyProperty.UnsetValue)
If itemFound Then Return item
element = VisualTreeHelper.GetParent(element)
End While
Return Nothing
End Function
Private Sub myListBox_PreviewMouseMove(ByVal sender As Object, ByVal e As System.Windows.Input.MouseEventArgs) Handles myListBox.PreviewMouseMove
If m_IsDown Then
If Math.Abs(e.GetPosition(myListBox).X - m_StartPoint.X) > SystemParameters.MinimumHorizontalDragDistance AndAlso _
Math.Abs(e.GetPosition(myListBox).Y - m_StartPoint.Y) > SystemParameters.MinimumVerticalDragDistance Then
DragStarted()
End If
End If
End Sub
Private Sub DragStarted()
m_IsDown = False
Dim serializedObject As String = m_OriginalElement.OuterXml
Dim data As DataObject = New DataObject()
data.SetData(m_MyFormat.Name, serializedObject)
Dim effects As DragDropEffects = _
DragDrop.DoDragDrop(myListBox, data, DragDropEffects.Copy Or DragDropEffects.Move)
If effects And DragDropEffects.Move Then
' Remove the element.
m_OriginalElement.ParentNode.RemoveChild(m_OriginalElement)
m_OriginalElement = Nothing
End If
End Sub
Private Sub DragMoved()
Dim currentPosition As Point = System.Windows.Input.Mouse.GetPosition(myListBox)
m_OverlayElement.LeftOffset = currentPosition.X - m_StartPoint.X
m_OverlayElement.TopOffset = currentPosition.Y - m_StartPoint.Y
End Sub
Private Sub myListBox_PreviewDragOver(ByVal sender As Object, ByVal e As System.Windows.DragEventArgs) Handles myListBox.PreviewDragOver
If Not UpdateEffects(e) Then
Exit Sub
End If
Dim currentPosition As Point = e.GetPosition(Me.Content)
m_OverlayElement.LeftOffset = currentPosition.X
m_OverlayElement.TopOffset = currentPosition.Y
e.Handled = True
End Sub
Private Sub myListBox_PreviewDrop(ByVal sender As Object, ByVal e As System.Windows.DragEventArgs) Handles myListBox.PreviewDrop
If Not UpdateEffects(e) Then
Exit Sub
End If
' Add the element.
Dim dataProvider As XmlDataProvider = FindResource("MyData")
Dim document As System.Xml.XmlDocument = dataProvider.Document
Dim node As System.Xml.XmlElement = dataProvider.Document.ImportNode(m_RemoteElement, True)
dataProvider.Document.GetElementsByTagName("Section")(0).AppendChild(node)
' Cleanup
AdornerLayer.GetAdornerLayer(Me.Content).Remove(m_OverlayElement)
m_RemoteElement = Nothing
m_OverlayElement = Nothing
e.Handled = True
End Sub
Private Sub myListBox_PreviewDragEnter(ByVal sender As Object, ByVal e As System.Windows.DragEventArgs) Handles myListBox.PreviewDragEnter
If Not UpdateEffects(e) Then
Exit Sub
End If
' First, we deserialize the object provided to us.
Dim serializedObject As String = e.Data.GetData(m_MyFormat.Name)
Dim document As System.Xml.XmlDocument = New System.Xml.XmlDocument()
document.LoadXml(serializedObject)
m_RemoteElement = document.DocumentElement
' Now, create something we can render with.
Dim presenter As ContentPresenter = New ContentPresenter()
presenter.Content = m_RemoteElement
presenter.ContentTemplate = myListBox.ItemTemplate
' Next, create an adorner for it.
Dim layer As AdornerLayer
m_OverlayElement = New DropPreviewAdorner(Me.Content, presenter)
layer = AdornerLayer.GetAdornerLayer(Me.Content)
layer.Add(m_OverlayElement)
e.Handled = True
End Sub
Private Sub myListBox_PreviewDragLeave(ByVal sender As Object, ByVal e As System.Windows.DragEventArgs) Handles myListBox.PreviewDragLeave
If m_OverlayElement Is Nothing Then Exit Sub
AdornerLayer.GetAdornerLayer(Me.Content).Remove(m_OverlayElement)
m_OverlayElement = Nothing
m_RemoteElement = Nothing
e.Handled = True
End Sub
Private Function UpdateEffects(ByVal e As System.Windows.DragEventArgs) As Boolean
' If we don't know what we're talking about, we shouldn't do anything.
If Not e.Data.GetDataPresent(m_MyFormat.Name) Then
e.Effects = DragDropEffects.None
Return False
End If
' If we can't copy or move, we shouldn't do anything (eg: provider wants us to link).
If (e.AllowedEffects And DragDropEffects.Copy) = 0 AndAlso _
(e.AllowedEffects And DragDropEffects.Move) = 0 Then
e.Effects = DragDropEffects.None
Return False
End If
' Figure out whether we should copy or move. If we can do either, we'll move unless
' Ctrl is pressed.
If (e.AllowedEffects And DragDropEffects.Copy) <> 0 AndAlso _
(e.AllowedEffects And DragDropEffects.Move) <> 0 Then
If (e.KeyStates And DragDropKeyStates.ControlKey) <> 0 Then
e.Effects = DragDropEffects.Copy
Else
e.Effects = DragDropEffects.Move
End If
Else
e.Effects = e.AllowedEffects And Not (DragDropEffects.Copy Or DragDropEffects.Move)
End If
Return True
End Function
End Class
Inherits Window
Class DropPreviewAdorner
Inherits Adorner
Public Sub New(ByVal adornedElement As UIElement, _
ByVal adorningElement As UIElement)
MyBase.New(adornedElement)
Dim brush As VisualBrush = New VisualBrush(adorningElement)
m_Child = New Rectangle()
m_Child.Width = adorningElement.RenderSize.Width
m_Child.Height = adorningElement.RenderSize.Height
m_Child.Fill = brush
m_Child.IsHitTestVisible = False
Dim animation As System.Windows.Media.Animation.DoubleAnimation
animation = New System.Windows.Media.Animation.DoubleAnimation(0.3, 1, New Duration(TimeSpan.FromSeconds(1)))
animation.AutoReverse = True
animation.RepeatBehavior = System.Windows.Media.Animation.RepeatBehavior.Forever
brush.BeginAnimation(System.Windows.Media.Brush.OpacityProperty, animation)
End Sub
' Adding some basic fields to help us keep track of where we are and what we render
Private m_Child As Rectangle
Private m_LeftOffset As Double
Private m_TopOffset As Double
Protected Overrides Function MeasureOverride(ByVal constraint As System.Windows.Size) As System.Windows.Size
m_Child.Measure(constraint)
Return m_Child.DesiredSize
End Function
Protected Overrides Function ArrangeOverride(ByVal finalSize As System.Windows.Size) As System.Windows.Size
m_Child.Arrange(New Rect(finalSize))
Return finalSize
End Function
Protected Overrides Function GetVisualChild(ByVal index As Integer) As System.Windows.Media.Visual
Return m_Child
End Function
Protected Overrides ReadOnly Property VisualChildrenCount() As Integer
Get
Return 1
End Get
End Property
Public Property LeftOffset() As Double
Get
Return m_LeftOffset
End Get
Set(ByVal value As Double)
m_LeftOffset = value
UpdatePosition()
End Set
End Property
Public Property TopOffset() As Double
Get
Return m_TopOffset
End Get
Set(ByVal value As Double)
m_TopOffset = value
UpdatePosition()
End Set
End Property
Private Sub UpdatePosition()
Dim adornerLayer As AdornerLayer = Me.Parent
If Not adornerLayer Is Nothing Then
adornerLayer.Update(AdornedElement)
End If
End Sub
Public Overrides Function GetDesiredTransform(ByVal transform As System.Windows.Media.GeneralTransform) As System.Windows.Media.GeneralTransform
Dim result As GeneralTransformGroup = New GeneralTransformGroup()
result.Children.Add(MyBase.GetDesiredTransform(transform))
result.Children.Add(New TranslateTransform(LeftOffset, TopOffset))
Return result
End Function
End Class
Private m_StartPoint As Point ' Where did the mouse start off from?
Private m_IsDown As Boolean ' Is the mouse down right now?
Private m_OriginalElement As System.Xml.XmlElement ' What is it that we're dragging?
Private m_OverlayElement As DropPreviewAdorner ' What is it that we're using to show
Private m_RemoteElement As System.Xml.XmlElement
Private Shared m_MyFormat As DataFormat = DataFormats.GetDataFormat("My Love-ly Format")
Public Sub New()
InitializeComponent()
End Sub
Private Sub myListBox_PreviewMouseLeftButtonDown(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles myListBox.PreviewMouseLeftButtonDown
m_OriginalElement = GetElementFromPoint(myListBox, e.GetPosition(myListBox))
If m_OriginalElement Is Nothing Then Exit Sub
m_IsDown = True
m_StartPoint = e.GetPosition(myListBox)
End Sub
Private Function GetElementFromPoint(ByVal box As ListBox, ByVal point As Point) As System.Xml.XmlElement
Dim element As UIElement = box.InputHitTest(point)
While True
If element Is box Then Return Nothing
Dim item As Object = box.ItemContainerGenerator.ItemFromContainer(element)
Dim itemFound As Boolean = Not item.Equals(DependencyProperty.UnsetValue)
If itemFound Then Return item
element = VisualTreeHelper.GetParent(element)
End While
Return Nothing
End Function
Private Sub myListBox_PreviewMouseMove(ByVal sender As Object, ByVal e As System.Windows.Input.MouseEventArgs) Handles myListBox.PreviewMouseMove
If m_IsDown Then
If Math.Abs(e.GetPosition(myListBox).X - m_StartPoint.X) > SystemParameters.MinimumHorizontalDragDistance AndAlso _
Math.Abs(e.GetPosition(myListBox).Y - m_StartPoint.Y) > SystemParameters.MinimumVerticalDragDistance Then
DragStarted()
End If
End If
End Sub
Private Sub DragStarted()
m_IsDown = False
Dim serializedObject As String = m_OriginalElement.OuterXml
Dim data As DataObject = New DataObject()
data.SetData(m_MyFormat.Name, serializedObject)
Dim effects As DragDropEffects = _
DragDrop.DoDragDrop(myListBox, data, DragDropEffects.Copy Or DragDropEffects.Move)
If effects And DragDropEffects.Move Then
' Remove the element.
m_OriginalElement.ParentNode.RemoveChild(m_OriginalElement)
m_OriginalElement = Nothing
End If
End Sub
Private Sub DragMoved()
Dim currentPosition As Point = System.Windows.Input.Mouse.GetPosition(myListBox)
m_OverlayElement.LeftOffset = currentPosition.X - m_StartPoint.X
m_OverlayElement.TopOffset = currentPosition.Y - m_StartPoint.Y
End Sub
Private Sub myListBox_PreviewDragOver(ByVal sender As Object, ByVal e As System.Windows.DragEventArgs) Handles myListBox.PreviewDragOver
If Not UpdateEffects(e) Then
Exit Sub
End If
Dim currentPosition As Point = e.GetPosition(Me.Content)
m_OverlayElement.LeftOffset = currentPosition.X
m_OverlayElement.TopOffset = currentPosition.Y
e.Handled = True
End Sub
Private Sub myListBox_PreviewDrop(ByVal sender As Object, ByVal e As System.Windows.DragEventArgs) Handles myListBox.PreviewDrop
If Not UpdateEffects(e) Then
Exit Sub
End If
' Add the element.
Dim dataProvider As XmlDataProvider = FindResource("MyData")
Dim document As System.Xml.XmlDocument = dataProvider.Document
Dim node As System.Xml.XmlElement = dataProvider.Document.ImportNode(m_RemoteElement, True)
dataProvider.Document.GetElementsByTagName("Section")(0).AppendChild(node)
' Cleanup
AdornerLayer.GetAdornerLayer(Me.Content).Remove(m_OverlayElement)
m_RemoteElement = Nothing
m_OverlayElement = Nothing
e.Handled = True
End Sub
Private Sub myListBox_PreviewDragEnter(ByVal sender As Object, ByVal e As System.Windows.DragEventArgs) Handles myListBox.PreviewDragEnter
If Not UpdateEffects(e) Then
Exit Sub
End If
' First, we deserialize the object provided to us.
Dim serializedObject As String = e.Data.GetData(m_MyFormat.Name)
Dim document As System.Xml.XmlDocument = New System.Xml.XmlDocument()
document.LoadXml(serializedObject)
m_RemoteElement = document.DocumentElement
' Now, create something we can render with.
Dim presenter As ContentPresenter = New ContentPresenter()
presenter.Content = m_RemoteElement
presenter.ContentTemplate = myListBox.ItemTemplate
' Next, create an adorner for it.
Dim layer As AdornerLayer
m_OverlayElement = New DropPreviewAdorner(Me.Content, presenter)
layer = AdornerLayer.GetAdornerLayer(Me.Content)
layer.Add(m_OverlayElement)
e.Handled = True
End Sub
Private Sub myListBox_PreviewDragLeave(ByVal sender As Object, ByVal e As System.Windows.DragEventArgs) Handles myListBox.PreviewDragLeave
If m_OverlayElement Is Nothing Then Exit Sub
AdornerLayer.GetAdornerLayer(Me.Content).Remove(m_OverlayElement)
m_OverlayElement = Nothing
m_RemoteElement = Nothing
e.Handled = True
End Sub
Private Function UpdateEffects(ByVal e As System.Windows.DragEventArgs) As Boolean
' If we don't know what we're talking about, we shouldn't do anything.
If Not e.Data.GetDataPresent(m_MyFormat.Name) Then
e.Effects = DragDropEffects.None
Return False
End If
' If we can't copy or move, we shouldn't do anything (eg: provider wants us to link).
If (e.AllowedEffects And DragDropEffects.Copy) = 0 AndAlso _
(e.AllowedEffects And DragDropEffects.Move) = 0 Then
e.Effects = DragDropEffects.None
Return False
End If
' Figure out whether we should copy or move. If we can do either, we'll move unless
' Ctrl is pressed.
If (e.AllowedEffects And DragDropEffects.Copy) <> 0 AndAlso _
(e.AllowedEffects And DragDropEffects.Move) <> 0 Then
If (e.KeyStates And DragDropKeyStates.ControlKey) <> 0 Then
e.Effects = DragDropEffects.Copy
Else
e.Effects = DragDropEffects.Move
End If
Else
e.Effects = e.AllowedEffects And Not (DragDropEffects.Copy Or DragDropEffects.Move)
End If
Return True
End Function
End Class