Wiki


Wiki Table of Contents

Page Details

Published by:
This page has not yet been rated

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

Filed under: [Edit Tags]

Về bài hướng dẫn này chúng ta sẽ thực hiện từng bước, những gì cơ bản bạn cần có để tạo một dialog (hộp thoại) mà bạn có thể:

  1. Drag/drop.( Kéo/ thả)
  2. Add transparency (opacity) to.(Làm cho hộp thoại trở nên  trong suốt (mờ))
  3. Round the corners.( Làm tròn các góc của hộp thoại)

Để xem trước và chạy ứng dụng này bạn có thể xem tại đây: http://silverlight.services.live.com/invoke/66033/Border%20Demo/iframe.html. Hãy di chuyển qua trái phải thanh trượt ngang bằng chuột trái để xem độ trong suốt thay đổi như thế nào, độ tròn các góc  cũng thay đổi, và có thể kéo thả vị trí của hộp thoại.

Bước 1: Tạo một hộp thoại trong suốt với các góc được bo tròn

Về nền của hộp thoại ta sử dụng control (công cụ)   Border .  Những control  Border  cho phép bạn sử dụng một thuộc tính là  CornerRadius  được dùng để thực hiện làm tròn các góc của 1 border (khung hình ) . Bạn cũng có thể đặt giá trị cho  độ Opacity cho hộp thoại là mức độ trong suốt mà bạn muốn có.

Đây là mã XAML  cho phần  Border của chúng ta:

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

Opacity chạy từ  0.0 – 1.0. với các điểm sẽ làm tăng độ trong suốt hay giảm độ trong suốt của đối tượng sử dụng thuộc tính này . Và demo của chúng ta, mỗi vị trị của thanh trượt đại diện cho sự thay đổi độ trong suốt là 0.01.

image

Borders chạy từ  0 – 150. Tại 150, Bạn sẽ có 1 hình tròn hoàn hảo. Tại  0, hộp thoại là 1 hình vuông.

image

Để thay đổi giá trị, chúng ta kiểm soát thanh trượt và gán giá trị của control  Border như sau:

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();
}

Bước 2. Thêm hàm kéo/ thả vào dialog sử dụng CaptureMouse().

Để sử dụng thuộc tính drag/drop kéo/ thả của hộp thoại chúng ta sẽ cần đến:

  1. Thêm một sự kiện cho control để giám sát cho MouseLeftButtonDown().
  2. Thêm một sự kiện cho control để giám sát cho MouseMove().
  3. Thêm một sự kiện cho control để giám sát cho MouseLeftButtonUp().

Trong MouseLeftButtonDown() chúng ta :

  1. Tạo một hàm gọi  CaptureMouse(). Bằng cách này nếu chuột được di chuyển nhanh đủ để thoát khỏi sự kiểm soát, chúng ta sẽ có thể  tiếp tục kiểm soát   sự di chuyển của chuột.
  2. Nắm lấy điểm cuối cùng mà trỏ chuột được click. Bằng cách này khi chuột được di chuyển, chúng ta có thể tính toán được từ các điểm di chuyển khác nhau.
  3. Lấy được khoảng cách trong hộp thoại nơi con chuột được click.
  4. Gán  _isDragging = true để chúng ta bắt đầu kiểm soát sự di chuyển của chuột.
   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: }

Trong  MouseMove() chúng ta :

  1. Lấy vị trí hiện thời của chuột và tình toán khoảng cách bao xa mà nó di chuyển được dựa vào  điểm cuối cùng.
  2. Cập nhật lại vị trí mới của hộp thoại  dựa trên khoảng cách chuột.
  3. Nắm lấy điểm cuối cùng của chúng ta.
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;
    }
}

Trong  MouseLeftButtonUp() chúng ta :

  1. Gán  _isDragging = false để chấm dứt việc điều khiển sự di chuyển của chuột.
  2. Phóng thích quyền điều khiển chuột.
void DialogSample_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
   _isDragging = false;
   this.ReleaseMouseCapture();
}

Đây là phần code hoàn chỉnh cho hộp thoại của chúng ta:

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

Recent Comments

By: Võ Đình Vinh Posted on 04-07-2010 5:06 PM

Có thể viết đơn giản cho vị dụ này như sau: Thay vì cách viết rất dài như trên

<CODE>

<Grid>  

   <Grid.ColumnDefinitions>

     <ColumnDefinition Width="Auto"></ColumnDefinition>

     <ColumnDefinition Width="Auto"></ColumnDefinition>

   </Grid.ColumnDefinitions>

   <Grid.RowDefinitions>

     <RowDefinition Height="Auto"></RowDefinition>

     <RowDefinition Height="Auto"></RowDefinition>

     <RowDefinition Height="Auto"></RowDefinition>

   </Grid.RowDefinitions>

   <Label Grid.Row="0" Grid.Column="0" Content="Opacity"></Label>

   <Label Grid.Row="1" Grid.Column="0" Content="Borders"></Label>

   <Slider Maximum="1" x:Name="Opa" Grid.Row="0" Grid.Column="1" Width="100" Margin="3"></Slider>

   <Slider Maximum="100" x:Name="Cor" Grid.Row="1" Grid.Column="1" Width="100" Margin="3"></Slider>

   <Border Margin="3" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" Opacity="{Binding Value,ElementName=Opa}" CornerRadius="{Binding Value,ElementName=Cor}" Width="300" Height="300" BorderBrush="White" Background="Black" BorderThickness="1">

   </Border>

 </Grid>

</CODE>