Wpf 实现拖拽效果

时间:2022-11-03 14:50:39

1、设置源控件和目标控件的AllowDrop=true

listBox1.AllowDrop = true;

 <Style TargetType="ListBoxItem">

            <Setter Property="ContentTemplate">

                <Setter.Value>

                    <DataTemplate>

                        <StackPanel Name="grid">

                            <Image Source="{Binding}"/>

                            <TextBlock Text="{Binding}"/>

                        </StackPanel>

                    </DataTemplate>

                </Setter.Value>

            </Setter>

            <EventSetter Event="ListBoxItem.PreviewMouseMove" Handler="lbi_PreviewMouseMove"/>

            <EventSetter Event="ListBoxItem.QueryContinueDrag" Handler="lbi_QueryContinueDrag"/>

            <EventSetter Event="ListBoxItem.GiveFeedback" Handler="lbi_GiveFeedback"/>

        </Style>

2、源控件的PreviewMouseMove事件来控制拖动的数据以及效果

AdornerLayer mAdornerLayer = null;

 void lbi_PreviewMouseMove(object sender, MouseEventArgs e)

        {

            ListBoxItem li = sender as ListBoxItem;

            if (li != null && li.IsSelected)

            {

                DragDropAdorner adorner = new DragDropAdorner(li);(DragDropAdorner实现Adorner抽象类)

                mAdornerLayer = AdornerLayer.GetAdornerLayer(grid);                    

 mAdornerLayer.Add(adorner);

                DataObject dob = new DataObject(li);

                DragDrop.DoDragDrop(li, dob, DragDropEffects.Copy);//启动拖拽

                mAdornerLayer.Remove(adorner);

            }

        }

public class DragDropAdorner : Adorner

    {

        public DragDropAdorner(UIElement parent)

            : base(parent)

        {

            IsHitTestVisible = false; // Seems Adorner is hit test visible?

            mDraggedElement = parent as FrameworkElement;

        }

 

        protected override void OnRender(DrawingContext drawingContext)

        {

            base.OnRender(drawingContext);

 

            if (mDraggedElement != null)

            {

                Win32.POINT screenPos = new Win32.POINT();

                if (Win32.GetCursorPos(ref screenPos))

                {

                    Point pos = PointFromScreen(new Point(screenPos.X, screenPos.Y));

                    Rect rect = new Rect(pos.X, pos.Y, mDraggedElement.ActualWidth, mDraggedElement.ActualHeight);

                    drawingContext.PushOpacity(1.0);

                    Brush highlight = mDraggedElement.TryFindResource(SystemColors.HighlightBrushKey) as Brush;

                    if (highlight != null)

                        drawingContext.DrawRectangle(highlight, new Pen(Brushes.Transparent, 0), rect);

                    drawingContext.DrawRectangle(new VisualBrush(mDraggedElement),

                        new Pen(Brushes.Transparent, 0), rect);

                    drawingContext.Pop();

                }

            }

        }

 

        FrameworkElement mDraggedElement = null;

    }

 

    public static class Win32

    {

        public struct POINT { public Int32 X; public Int32 Y; }

 

        // During drag-and-drop operations, the position of the mouse cannot be

        // reliably determined through GetPosition. This is because control of

        // the mouse (possibly including capture) is held by the originating

        // element of the drag until the drop is completed, with much of the

        // behavior controlled by underlying Win32 calls. As a workaround, you

        // might need to use Win32 externals such as GetCursorPos.

        [DllImport("user32.dll")]

        public static extern bool GetCursorPos(ref POINT point);

    }

3、目标控件接收数据,使用DragDrop.Drop事件(以Button为例DragDrop.Drop="button1_Drop")

            private void button1_Drop(object sender, DragEventArgs e)

        {

            Point p = e.GetPosition(button1);

            HitTestResult result = VisualTreeHelper.HitTest(button1, p);

            if (result == null)

                return ;

            ListBoxItem li=e.Data.GetData(typeof(ListBoxItem)) as ListBoxItem;

        }

注:参见http://www.cnblogs.com/loveis715/archive/2011/12/05/2277384.html