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: https://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=\"https://schemas.microsoft.com/winfx/2006/xaml/presentation\"" +
             "                  xmlns:x=\"https://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