Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

WPF Draggable Label

, 13 Apr 2010 CPOL
WPF label control that can be dragged and resized at runtime
DraggableLabel_demo.zip
DraggableLabelTest
bin
Release
DraggableLabelTest.exe
DraggableLabelTest.pdb
DraggableLabelTest.vshost.exe
DraggableLabelTest.vshost.exe.manifest
RtwControls.DraggableLabel.dll
RtwControls.DraggableLabel.pdb
WPFToolkit.dll
WPFToolkit.pdb
Properties
Settings.settings
DraggableLabel_src.zip
DraggableLabel
bin
Release
RtwControls.DraggableLabel.dll
RtwControls.DraggableLabel.pdb
Properties
Settings.settings
Themes
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace RtwControls
{
    #region Event Handlers

    public delegate void DraggableLabelDragHandler(object sender, DraggableLabelDragEventArgs e);
    public delegate void DraggableLabelResizeHandler(object sender, DraggableLabelResizeEventArgs e);

    #endregion

    /// <summary>
    /// Label control which can be dragged and resized at runtime
    /// </summary>
    public class DraggableLabel : Label
    {
        #region Events

        public event DraggableLabelDragHandler Drag;
        public event DraggableLabelResizeHandler Resize;

        #endregion

        #region Member Variables

        private Point _previousLocation;
        private Transform _previousTransform;

        #endregion

        #region Constructors

        /// <summary>
        /// Static constructor
        /// </summary>
        static DraggableLabel()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(DraggableLabel), new FrameworkPropertyMetadata(typeof(Label)));
        }

        /// <summary>
        /// Default constructor
        /// </summary>
        public DraggableLabel()
        {
        }

        #endregion

        #region Methods

        protected void OnDrag(DraggableLabelDragEventArgs e)
        {
            DraggableLabelDragHandler handler = Drag;
            if (handler != null) handler(this, e);
        }

        protected void OnResize(DraggableLabelResizeEventArgs e)
        {
            DraggableLabelResizeHandler handler = Resize;
            if (handler != null) handler(this, e);
        }

        #endregion

        #region Overrides

        protected override void OnMouseEnter(MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                this.CaptureMouse();
            }

            base.OnMouseEnter(e);
        }

        protected override void OnMouseLeave(MouseEventArgs e)
        {
            this.ReleaseMouseCapture();
            base.OnMouseLeave(e);
        }

        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            this.ReleaseMouseCapture();
            base.OnMouseLeftButtonUp(e);
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            this.CaptureMouse();
            base.OnMouseLeftButtonDown(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            Window wnd = Window.GetWindow(this);
            Point currentLocation = e.MouseDevice.GetPosition(wnd);

            var move = new TranslateTransform(
                    currentLocation.X - _previousLocation.X, currentLocation.Y - _previousLocation.Y);

            double width = double.IsNaN(this.Width) ? this.ActualWidth : this.Width;
            double height = double.IsNaN(this.Height) ? this.ActualHeight : this.Height;

            if (e.LeftButton == MouseButtonState.Pressed)
            {
                if (this.Cursor == Cursors.Hand)
                {
                    var group = new TransformGroup();
                    if (_previousTransform != null)
                    {
                        group.Children.Add(_previousTransform);
                    }
                    group.Children.Add(move);

                    this.RenderTransform = group;

                    // Invoke drag event
                    OnDrag(new DraggableLabelDragEventArgs(currentLocation));
                }
                else if (this.Cursor == Cursors.SizeWE)
                {
                    if (width + currentLocation.X - _previousLocation.X > this.MinWidth)
                    {
                        this.Width = width + currentLocation.X - _previousLocation.X;
                    }

                    // Invoke resize event
                    OnResize(new DraggableLabelResizeEventArgs(new Size(this.Width, this.Height)));
                }
                else if (this.Cursor == Cursors.SizeNS)
                {
                    if (height + currentLocation.Y - _previousLocation.Y > this.MinHeight)
                    {
                        this.Height = height + currentLocation.Y - _previousLocation.Y;
                    }

                    // Invoke resize event
                    OnResize(new DraggableLabelResizeEventArgs(new Size(this.Width, this.Height)));
                }
            }
            else
            {
                const int dragHandleWidth = 3;

                var bottomHandle = new Rect(0, height - dragHandleWidth, width, dragHandleWidth);
                var rightHandle = new Rect(width - dragHandleWidth, 0, dragHandleWidth, height);

                Point relativeLocation = wnd.TranslatePoint(currentLocation, this);

                if (rightHandle.Contains(relativeLocation))
                {
                    this.Cursor = Cursors.SizeWE;
                }
                else if (bottomHandle.Contains(relativeLocation))
                {
                    this.Cursor = Cursors.SizeNS;
                }
                else
                {
                    this.Cursor = Cursors.Hand;
                }
            }

            _previousLocation = currentLocation;
            _previousTransform = this.RenderTransform;

            base.OnMouseMove(e);
        }

        public override string ToString()
        {
            string details = string.Empty;

            double width = this.Width == double.NaN ? this.ActualWidth : this.Width;
            double height = this.Height == double.NaN ? this.ActualHeight : this.Height;

            if (this.Cursor == Cursors.Hand)
            {
                Window wnd = Window.GetWindow(this);
                Point location = this.TranslatePoint(new Point(0, 0), wnd);

                details = " : X = " + location.X + ", Y = " + location.Y;
            }
            else if (this.Cursor == Cursors.SizeWE)
            {
                details = " : Width2 = " + width;
            }
            else if (this.Cursor == Cursors.SizeNS)
            {
                details = " : Height2 = " + height;
            }

            return this.Name + details;
        }

        #endregion
    }

    #region Event Arguments

    /// <summary>
    /// Event arguments to be passed into the drag event.
    /// </summary>
    public class DraggableLabelDragEventArgs : EventArgs
    {
        private Point _location;

        public DraggableLabelDragEventArgs(Point location)
        {
            _location = location;
        }

        public int X
        {
            get
            {
                return (int)_location.X;
            }
        }

        public int Y
        {
            get
            {
                return (int)_location.Y;
            }
        }
    }

    /// <summary>
    /// Event arguments to be passed into the resize event.
    /// </summary>
    public class DraggableLabelResizeEventArgs : EventArgs
    {
        private Size _size;

        public DraggableLabelResizeEventArgs(Size size)
        {
            _size = size;
        }

        public int Width
        {
            get
            {
                return (int)_size.Width;
            }
        }

        public int Height
        {
            get
            {
                return (int)_size.Height;
            }
        }
    }

    #endregion
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rajitha Wimalasooriya
Software Developer
Australia Australia
No Biography provided

| Advertise | Privacy | Mobile
Web02 | 2.8.141022.2 | Last Updated 13 Apr 2010
Article Copyright 2010 by Rajitha Wimalasooriya
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid