WPF中的拖放(二)

2010年2月21日 分类: WPF

上一篇,我们实现了基本拖拽操作,今天,我们来实现,拖拽过程中鼠标跟随效果,这里我们要用到WPF新对象Adorner(装饰器)用来显示拖拽内容,如我们今天拖拽的矩形。首先,我们新建一个DragAdorner类,继承Adorner用来显示拖拽内容,代码如下

public class DragAdorner : Adorner
{
    #region 变量
    protected UIElement _child;
    protected VisualBrush _brush;
    protected UIElement _owner;
    protected double XCenter;
    protected double YCenter;

    private double _leftOffset;
    private double _topOffset;
    public double Scale = 1.0;
    #endregion

    #region 构造函数
    public DragAdorner(UIElement owner) : base(owner) { }

    public DragAdorner(UIElement owner, UIElement adornElement, double opacity)
        : base(owner)
    {
        this._owner = owner;
        VisualBrush _brush = new VisualBrush(adornElement);
        _brush.Opacity = opacity;
        Rectangle r = new Rectangle();
        r.RadiusX = 3;
        r.RadiusY = 3;

        r.Width = adornElement.DesiredSize.Width;
        r.Height = adornElement.DesiredSize.Height;

        XCenter = adornElement.DesiredSize.Width / 2;
        YCenter = adornElement.DesiredSize.Height / 2;

        r.Fill = _brush;
        this._child = r;
    }
    #endregion

    #region 属性
    public double LeftOffset
    {
        get { return this._leftOffset; }
        set
        {
            this._leftOffset = value - XCenter;
            this.UpdatePosition();
        }
    }

    public double TopOffset
    {
        get { return this._topOffset; }
        set
        {
            this._topOffset = value - YCenter;
            this.UpdatePosition();
        }
    }

    protected override int VisualChildrenCount
    {
        get
        {
            return 1;
        }
    }
    #endregion

    #region 方法
    private void UpdatePosition()
    {
        AdornerLayer adorner = (AdornerLayer)this.Parent;
        if (adorner != null)
        {
            adorner.Update(this.AdornedElement);
        }
    }

    protected override Visual GetVisualChild(int index)
    {
        return _child;
    }

    protected override Size MeasureOverride(Size finalSize)
    {
        this._child.Measure(finalSize);
        return this._child.DesiredSize;
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        this._child.Arrange(new Rect(_child.DesiredSize));
        return finalSize;
    }

    public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
    {
        GeneralTransformGroup result = new GeneralTransformGroup();

        result.Children.Add(base.GetDesiredTransform(transform));
        result.Children.Add(new TranslateTransform(this._leftOffset, this._topOffset));
        return result;
    }
    #endregion
}

我们声明几个对象,并且修改上篇代码中矩形的PreviewMouseMove事件

/// <summary>
/// 拖动的区域
/// </summary>
private FrameworkElement _dragScope;
/// <summary>
/// 用于显示鼠标跟随效果的装饰器
/// </summary>
private DragAdorner _adorner;
/// <summary>
/// 用于呈现DragAdorner的图画
/// </summary>
private AdornerLayer _layer;

void rectangle1_PreviewMouseMove(object sender, MouseEventArgs e)
{
    if (e.LeftButton == MouseButtonState.Pressed)
    {
        this.StartDrag(e);
    }
}

private void StartDrag(MouseEventArgs e)
{
    this._dragScope = Application.Current.MainWindow.Content as FrameworkElement;

    this._dragScope.AllowDrop = true;

    DragEventHandler draghandler = new DragEventHandler(DragScope_PreviewDragOver);
    this._dragScope.PreviewDragOver += draghandler;

    this._adorner = new DragAdorner(this._dragScope, (UIElement)this.rectangle1, 0.5);
    this._layer = AdornerLayer.GetAdornerLayer(this._dragScope as Visual);
    this._layer.Add(this._adorner);

    DataObject data = new DataObject(typeof(Rectangle), this.rectangle1);
    DragDrop.DoDragDrop(this.rectangle1, data, DragDropEffects.Move);

    AdornerLayer.GetAdornerLayer(this._dragScope).Remove(this._adorner);
    this._adorner = null;

    this._dragScope.PreviewDragOver -= draghandler;
}

void DragScope_PreviewDragOver(object sender, DragEventArgs args)
{
    if (this._adorner != null)
    {
        this._adorner.LeftOffset = args.GetPosition(this._dragScope).X;
        this._adorner.TopOffset = args.GetPosition(this._dragScope).Y;
    }

这样,就实现了,拖拽过程中显示跟随效果。关键代码就在StartDrag(MouseEventArgs)方法中,开始拖放的时候创建显示拖拽的对象,移动过程中更改装饰坐标,鼠标释放的时候移除装饰对象。看懂了之后,会发现WPF的拖拽并不复杂,但是,如何实现不同窗体之间的拖拽呢?后面我们会做介绍。

本文代码下载

原创文章,转载请注明: 转载自.NET开发者

本文链接地址: WPF中的拖放(二)

文章的脚注信息由WordPress的wp-posturl插件自动生成

Related posts:

  1. WPF中的Converter
  2. WPF中单击标题行可排序的GridView
  3. WPF中的拖放(三)
  4. WPF最大化避免覆盖任务栏
  5. MVVM(Model-View-ViewModel)实例讲解
标签: ,
目前还没有任何评论.

Leave a Comment