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

A Simple Solution to Some Problems with Asynchrony in Silverlight

, 9 Mar 2010
A small, extensible suite of classes that elegantly solve some common problems involving asynchrony and event handling that tend to occur when Silverlight and WCF are used together.
TaskManagerDemo.zip
TaskManagerDemo
Bin
Debug
Controls
Properties
Service References
ExampleServiceReference
configuration.svcinfo
configuration91.svcinfo
ExampleService.disco
ExampleService.wsdl
Reference.svcmap
TaskManagerDemo.ExampleServiceReference.CityZipCode.datasource
ServiceReferences.ClientConfig
Themes
Utility
TaskManagerDemo.Web
App_Data
bin
ClientBin
DataContracts
ExampleService.svc
Properties
TaskManagerDemo.Web.csproj.user
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace TaskManagerDemo.Controls
{
    [TemplatePart(Name = DragDropControl.rootElement, Type = typeof(Canvas))]
    [TemplatePart(Name = DragDropControl.containerElement, Type = typeof(Panel))]
    [TemplatePart(Name = DragDropControl.contentElement, Type = typeof(FrameworkElement))]

    public class DragDropControl : ContentControl
    {
        public event EventHandler PositionChanged;
        public event EventHandler Resized;

        private const string rootElement = "Root";
        private const string containerElement = "Container";
        private const string contentElement = "Content";

        #region Fields

        private Point oldPoint;
        private bool mouseDown = false;
        private string sizingDirection = string.Empty;
        private TranslateTransform transform;

        protected Canvas Root;
        protected Panel Container;

        #endregion Fields

        public DragDropControl()
        {
            this.DefaultStyleKey = typeof(DragDropControl);
            this.SetValue(Canvas.ZIndexProperty, DragDropControl.MaxZIndex);
            DragDropControl.MaxZIndex++;
            transform = new TranslateTransform();

            this.MouseLeftButtonDown += DragDropControl_MouseLeftButtonDown;
            this.MouseLeftButtonUp += DragDropControl_MouseLeftButtonUp;
            this.MouseMove += DragDropControl_MouseMove;
        }

        #region MaxZIndex

        /// <summary>
        /// Identifies the MaxZIndex dependency property.
        /// </summary>		
        public static int MaxZIndex;

        #endregion MaxZIndex
        #region CanResize

        /// <summary>
        /// Identifies the CanResize dependency property.
        /// </summary>
        public static readonly DependencyProperty CanResizeProperty = DependencyProperty.Register("CanResize", typeof(bool), typeof(DragDropControl), null);

        /// <summary>
        /// Gets or sets the CanResize possible Value of the bool object.
        /// </summary>
        public bool CanResize
        {
            get { return (bool)GetValue(CanResizeProperty); }
            set { SetValue(CanResizeProperty, value); }
        }

        #endregion CanResize
        #region OffsetX

        /// 
        /// Identifies the OffsetX dependency property.
        /// 
        public static readonly DependencyProperty OffsetXProperty = DependencyProperty.Register("OffsetX", typeof(double), typeof(DragDropControl), null);

        /// 
        /// Gets or sets the OffsetX possible Value of the int object.
        /// 
        public double OffsetX
        {
            get { return (double)GetValue(OffsetXProperty); }
            set
            {
                SetValue(OffsetXProperty, value);
                this.transform.X = value;
            }
        }

        #endregion OffsetX
        #region OffsetY

        /// 
        /// Identifies the OffsetY dependency property.
        /// 
        public static readonly DependencyProperty OffsetYProperty = DependencyProperty.Register("OffsetY", typeof(double), typeof(DragDropControl), null);

        /// 
        /// Gets or sets the OffsetY possible Value of the int object.
        /// 
        public double OffsetY
        {
            get { return (double)GetValue(OffsetYProperty); }
            set
            {
                SetValue(OffsetYProperty, value);
                this.transform.Y = value;
            }
        }

        #endregion OffsetY

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            Root = GetTemplateChild(rootElement) as Canvas;
            Container = GetTemplateChild(containerElement) as Panel;
            if (Container == null)
                throw new Exception(containerElement + " is Missing in the template");
            this.RenderTransform = transform;
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            Size s = base.ArrangeOverride(finalSize);
            if (this.Width.ToString() == "NaN")
                this.Width = this.Container.ActualWidth;
            if (this.Height.ToString() == "NaN")
                this.Height = this.Container.ActualHeight;
            return s;
        }

        #region Mouse Events

        private void DragDropControl_MouseMove(object sender, MouseEventArgs e)
        {
            Point m_newPoint = e.GetPosition(null);
            if (mouseDown)
            {
                if (sizingDirection == string.Empty)
                {
                    // Moving the Panel	
                    double x, y, mainX, mainY;
                    MainPage parent = App.Current.RootVisual as MainPage;
                    if (parent != null)
                    {
                        x = e.GetPosition(null).X;
                        y = e.GetPosition(null).Y;
                        mainX = e.GetPosition(parent).X;
                        mainY = e.GetPosition(parent).Y;

                        if (((mainX > 0) && (mainX < parent.ActualWidth - 10.0)) && ((mainY > 20) && (mainY < parent.ActualHeight - this.Height - 20)))
                        {
                            this.OffsetX += m_newPoint.X - oldPoint.X;
                            this.OffsetY += m_newPoint.Y - oldPoint.Y;
                            RaisePositionChanged();
                        }
                    }
                }
                else
                {
                    // Resizing the Panel
                    Panel p = this.Parent as Panel;

                    Point change = new Point(m_newPoint.X - oldPoint.X, m_newPoint.Y - oldPoint.Y);
                    UIElement c = this.Content as UIElement;
                    if (sizingDirection.IndexOf("n") > -1 && this.Height - change.Y > 2) //North
                    {
                        this.OffsetY += change.Y;
                        this.Height -= change.Y;
                        RaisePositionChanged();
                        RaiseResized();
                    }
                    if (sizingDirection.IndexOf("s") > -1 && this.Height + change.Y > 2) //South
                    {
                        this.Height += change.Y;
                        RaiseResized();
                    }
                    if (sizingDirection.IndexOf("w") > -1 && this.Width - change.X > 2) //West
                    {
                        this.OffsetX += change.X;
                        this.Width -= change.X;
                        RaisePositionChanged();
                        RaiseResized();
                    }
                    if (sizingDirection.IndexOf("e") > -1 && this.Width + change.X > 2) //East
                    {
                        this.Width += change.X;
                    }
                }
                oldPoint = m_newPoint;
            }
            else
            {
                // Check to see if mouse is on a resize area
                if (this.CanResize)
                {
                    sizingDirection = ResizeHitTest(m_newPoint);
                    SetCursor(sizingDirection);
                }
            }
        }

        private void DragDropControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (mouseDown)
            {
                this.Opacity = 1;
                this.ReleaseMouseCapture();
                mouseDown = false;
            }
        }

        private void DragDropControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.Handled)
                return;

            mouseDown = true;
            oldPoint = e.GetPosition(null);
            this.Opacity *= 0.8;
            this.CaptureMouse();
            int zIndex = (int)this.GetValue(Canvas.ZIndexProperty);
            if (zIndex > DragDropControl.MaxZIndex)
                DragDropControl.MaxZIndex = zIndex + 1;
            else if (zIndex < DragDropControl.MaxZIndex)
                DragDropControl.MaxZIndex++;
            this.SetValue(Canvas.ZIndexProperty, DragDropControl.MaxZIndex);
        }

        #endregion Mouse Events
        #region Helper Methods

        private string ResizeHitTest(Point pt)
        {
            double x0 = pt.X;
            double y0 = pt.Y;

            Point P = Position.GetAbsolutePosition(Container);

            double x1 = P.X;
            double y1 = P.Y;
            double x2 = x1 + Container.ActualWidth;
            double y2 = y1 + Container.ActualHeight;

            // Corners
            if (Math.Abs(x0 - x1) < 6 && Math.Abs(y0 - y1) < 6)
                sizingDirection = "nw";
            else if (Math.Abs(x0 - x1) < 6 && Math.Abs(y2 - y0) < 6)
                sizingDirection = "sw";
            else if (Math.Abs(x2 - x0) < 6 && Math.Abs(y2 - y0) < 6)
                sizingDirection = "se";
            else if (Math.Abs(x2 - x0) < 6 && Math.Abs(y0 - y1) < 6)
                sizingDirection = "ne";
            // Sides
            else if (Math.Abs(y0 - y1) < 4)
                sizingDirection = "n";
            else if (Math.Abs(x2 - x0) < 4)
                sizingDirection = "e";
            else if (Math.Abs(y2 - y0) < 4)
                sizingDirection = "s";
            else if (Math.Abs(x0 - x1) < 4)
                sizingDirection = "w";
            else
                sizingDirection = string.Empty;

            return sizingDirection;
        }

        private void SetCursor(string resize)
        {
            if (resize == "n" || resize == "s")
                Cursor = Cursors.SizeNS;
            else if (resize == "w" || resize == "e")
                Cursor = Cursors.SizeWE;
            else
                Cursor = Cursors.Arrow;
        }

        private void RaiseResized()
        {
            if (this.Resized != null)
                Resized(this, null);
        }

        private void RaisePositionChanged()
        {
            if (this.PositionChanged != null)
                PositionChanged(this, null);
        }

        #endregion Helper Methods
    }
}

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

George Henry 1954
Software Developer (Senior) Colibrium Partners. LLC
United States United States
George Henry has worked as a software developer for more than 20 years. He is currently employed by Colibrium in Bellevue, Washington, USA as a Technical Analyst, working on the company's Tuo software suite - both the base product and customizations for clients.

| Advertise | Privacy | Mobile
Web02 | 2.8.140902.1 | Last Updated 9 Mar 2010
Article Copyright 2009 by George Henry 1954
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid