Page view counter

Silverlight Tips of the Day - Blog by Mike Snow

Game Programming with Silverlight

Silverlight Tip of the Day #29: Creating a Transparent, Draggable Dialog with Rounded Corners

For this tutorial we will step you through the basics of what you need to do to create a dialog that you can:

  1. Drag/drop.
  2. Add transparency (opacity) to.
  3. Round the corners.

To preview and run this application please visit this link: http://silverlight.services.live.com/invoke/66033/Border%20Demo/iframe.html. Move any of the sliders as well as mouse left click, hold and drag/drop the dialog.

Step 1: Creating a Transparent Dialog with Rounded Corners

For the background of the dialog we will use a Border control. Border controls allow you to set a CornerRadius which is used to round the corners of the border. You can also set the Opacity level which is used to indicate the level of transparency you want for the control.

This is the XAML for our Border:

<Border x:Name="BorderDialog" Opacity="0.5" CornerRadius="10" Width="300" Height="300" BorderBrush="White" Background="Black" BorderThickness="1"></Border>

Opacity goes from 0.0 – 1.0. with floating point increments used to increase the level of Opacity. For our demo, each tick on the slider is represented by a 0.01 change in opacity.

image

Borders go from 0 – 150. At 150, you will have a complete circle. At 0, the dialog will be complete square.

image

To change the values we monitor the Sliders and set the values of the Border control like this:

void _borderSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    CornerRadius cr = new CornerRadius(_borderSlider.Value);
    _borderDialog.CornerRadius = cr;
    _borderValue.Text = ((int)_borderSlider.Value).ToString();
}
 
void _opacitySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    _borderDialog.Opacity = _opacitySlider.Value;
    _opacityValue.Text = Math.Round(_opacitySlider.Value, 2).ToString();
}

 Step 2. Add drag/drop functionality to the dialog using CaptureMouse().

In order to properly handle drag/drop of the dialog we will need to:

  1. Add an event for the control to monitor for MouseLeftButtonDown().
  2. Add an event for the control to monitor for MouseMove().
  3. Add an event for the control to monitor for MouseLeftButtonUp().

In MouseLeftButtonDown() we:

  1. Make a call to CaptureMouse(). This way if the mouse is moved quickly enough to escape the control we will continue to capture the mouse movement.
  2. Get  the last point where the Mouse was clicked. This way when the mouse is moved we can calculate the move difference.
  3. Get the offset into the dialog where the mouse was clicked.
  4. Set _isDragging = true so that we start processing mouse moves.
   1: void DialogSample_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
   2: {
   3:     this.CaptureMouse();
   4:  
   5:     _lastPoint = e.GetPosition(null);
   6:     double cx = (double)this.GetValue(Canvas.LeftProperty);
   7:     double cy = (double)this.GetValue(Canvas.TopProperty);
   8:     _offsetX = _lastPoint.X - cx;
   9:     _offsetY = _lastPoint.Y - cy;
  10:  
  11:     _isDragging = true;
  12:    
  13: }

In MouseMove() we:

  1. Get the current position of the mouse and calculate how far it moved based upon the last point.
  2. Update the dialog to the new position based upon the amount the mouse moved.
  3. Capture the last point we were at.
void DialogSample_MouseMove(object sender, MouseEventArgs e)
{
    if (true == _isDragging)
    {
        Point pt = e.GetPosition(null);
        double x = pt.X - _lastPoint.X;
        double y = pt.Y - _lastPoint.Y;
        double cx = (double) this.GetValue(Canvas.LeftProperty);
        double cy = (double)this.GetValue(Canvas.TopProperty);
        this.SetValue(Canvas.LeftProperty, cx+x);
        this.SetValue(Canvas.TopProperty, cy+y);
        _lastPoint = pt;
    }
}

In MouseLeftButtonUp() we:

  1. Set _isDragging = false to stop monitioring mouse moves.
  2. Release the mouse capture.
void DialogSample_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
   _isDragging = false;
   this.ReleaseMouseCapture();
}

Here is the complete code for this custom dialog control:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Markup;
 
namespace TransparentDialog
{
    public class DialogSample : Control
    {
 
        private string _toolbarTemplate =
            "<ControlTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"" +
            "                  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">" +
            "<Canvas x:Name=\"Toolbar\">" +
            "   <Border x:Name=\"BorderDialog\" Opacity=\"0.5\" CornerRadius=\"10\" Canvas.ZIndex=\"1\" Width=\"300\" Height=\"300\" BorderBrush=\"White\"  Background=\"Black\" BorderThickness=\"1\" >" +
            "   </Border>" +
            "   <TextBlock Canvas.ZIndex=\"10000\" Canvas.Top=\"70\"  Canvas.Left=\"50\" Foreground=\"White\">Opacity</TextBlock>" +
            "   <TextBlock Canvas.ZIndex=\"10000\" Canvas.Top=\"100\"  Canvas.Left=\"50\" Foreground=\"White\">Borders</TextBlock>" +
            "   <Slider Canvas.Top=\"70\" Canvas.Left=\"120\"  Canvas.ZIndex=\"10000\" Maximum=\"1.0\" Minimum=\"0.0\" SmallChange=\"0.01\" Value=\"0.5\" x:Name=\"OpacitySilder\" Width=\"100\"></Slider>" +
            "   <Slider Canvas.Top=\"100\" Canvas.Left=\"120\"  Canvas.ZIndex=\"10000\" Maximum=\"150.0\" Minimum=\"0.0\" SmallChange=\"1.0\" Value=\"20\" x:Name=\"BorderSilder\" Width=\"100\"></Slider>" +
            "   <TextBlock Canvas.ZIndex=\"10000\" x:Name=\"OpacityValue\" Canvas.Top=\"70\"  Canvas.Left=\"230\" Foreground=\"White\">Value</TextBlock>" +
            "   <TextBlock Canvas.ZIndex=\"10000\" x:Name=\"BorderValue\" Canvas.Top=\"100\"  Canvas.Left=\"230\" Foreground=\"White\">Value</TextBlock>" +
            "</Canvas>" +
            "</ControlTemplate>";
 
        private Canvas _dialogCanvas;
        private Border _borderDialog;
        private Slider _opacitySlider;
        private Slider _borderSlider;
        private bool _isDragging = false;
        private Point _lastPoint;
        private double _offsetX;
        private double _offsetY;
        private TextBlock _opacityValue;
        private TextBlock _borderValue;
 
        public DialogSample()
        {
            Template = (ControlTemplate)XamlReader.Load(_toolbarTemplate);
            ApplyTemplate();
        }
 
        void DialogSample_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
           _isDragging = false;
           this.ReleaseMouseCapture();
        }
 
        void DialogSample_MouseMove(object sender, MouseEventArgs e)
        {
            if (true == _isDragging)
            {
                Point pt = e.GetPosition(null);
                double x = pt.X - _lastPoint.X;
                double y = pt.Y - _lastPoint.Y;
                double cx = (double) this.GetValue(Canvas.LeftProperty);
                double cy = (double)this.GetValue(Canvas.TopProperty);
                this.SetValue(Canvas.LeftProperty, cx+x);
                this.SetValue(Canvas.TopProperty, cy+y);
                _lastPoint = pt;
            }
        }
 
        void DialogSample_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.CaptureMouse();
 
            _lastPoint = e.GetPosition(null);
            double cx = (double)this.GetValue(Canvas.LeftProperty);
            double cy = (double)this.GetValue(Canvas.TopProperty);
            _offsetX = _lastPoint.X - cx;
            _offsetY = _lastPoint.Y - cy;
 
            _isDragging = true;
           
        }
 
        public override void OnApplyTemplate()
        {
            _dialogCanvas = (Canvas)GetTemplateChild("Toolbar");
            _opacitySlider = (Slider)GetTemplateChild("OpacitySilder");
            _borderSlider = (Slider)GetTemplateChild("BorderSilder");
            _borderDialog = (Border)GetTemplateChild("BorderDialog");
            _opacityValue = (TextBlock)GetTemplateChild("OpacityValue");
            _borderValue = (TextBlock)GetTemplateChild("BorderValue");
 
            _borderSlider.Value = 20;
            _opacitySlider.Value = 0.5;
            _borderValue.Text = "20";
            _opacityValue.Text = "0.5";                
            _opacitySlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(_opacitySlider_ValueChanged);
            _borderSlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(_borderSlider_ValueChanged);
            
            this.MouseLeftButtonDown += new MouseButtonEventHandler(DialogSample_MouseLeftButtonDown);
            this.MouseMove += new MouseEventHandler(DialogSample_MouseMove);
            this.MouseLeftButtonUp += new MouseButtonEventHandler(DialogSample_MouseLeftButtonUp);
            this.SetValue(Canvas.TopProperty, (double)100);
            this.SetValue(Canvas.LeftProperty, (double)100);
 
        }
 
        void _borderSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            CornerRadius cr = new CornerRadius(_borderSlider.Value);
            _borderDialog.CornerRadius = cr;
            _borderValue.Text = ((int)_borderSlider.Value).ToString();
        }
 
        void _opacitySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            _borderDialog.Opacity = _opacitySlider.Value;
            _opacityValue.Text = Math.Round(_opacitySlider.Value, 2).ToString();
        }
 
    }
}

Thank you,
--Mike Snow

 Subscribe in a reader

Comments

Microsoft Weblogs said:

For this tutorial we will step you through the basics of what you need to do to create a dialog that

# August 19, 2008 4:12 PM

Pages tagged "snow" said:

Pingback from  Pages tagged "snow"

# August 19, 2008 5:03 PM

Community Blogs said:

Martin Mihaylov on Resizing the SL Object, Dan Wahlin on the Grid and a Flyout StackPanel, Robby Ingebretsen

# August 19, 2008 5:18 PM

2008 August 20 - Links for today « My (almost) Daily Links said:

Pingback from  2008 August 20 - Links for today &laquo; My (almost) Daily Links

# August 20, 2008 2:14 AM

Dew Drop - August 20, 2008 | Alvin Ashcraft's Morning Dew said:

Pingback from  Dew Drop - August 20, 2008 | Alvin Ashcraft's Morning Dew

# August 20, 2008 8:34 AM

Dew Drop - August 20, 2008 | Alvin Ashcraft's Morning Dew said:

Pingback from  Dew Drop - August 20, 2008 | Alvin Ashcraft's Morning Dew

# August 20, 2008 8:34 AM

Silverlight news for August 21, 2008 said:

Pingback from  Silverlight news for August 21, 2008

# August 21, 2008 10:55 AM

Mirrored Blogs said:

Post: Approved at: Aug-21-2008 Linux &amp; Silverlight Microsoft and Novell expanding their partnership

# August 21, 2008 12:51 PM

Visual Web Developer Team Blog said:

Silverlight Tip of the Day #32 &#160; Title : How to Declare a Custom User Control from a XAML Page.

# August 26, 2008 1:13 PM

News said:

Silverlight Tip of the Day #32 Title : How to Declare a Custom User Control from a XAML Page. Demo :

# August 26, 2008 2:57 PM

Recent URLs tagged Roundedcorners - Urlrecorder said:

Pingback from  Recent URLs tagged Roundedcorners - Urlrecorder

# October 24, 2008 2:46 AM

Silverlight Tips of the Day - Blog by Mike Snow said:

The purpose of this post is to create an outline summary all the blogs from my Silverlight tips of the

# January 2, 2009 5:56 PM

o UAU nosso de cada dia said:

essa lista eu copiei desse blog bárbaro (acompanhe por RSS você também): uma lista de dicas super úteis

# January 3, 2009 6:25 AM

ninkynonk said:

good guide

# March 31, 2009 7:00 AM