您的位置:首页 > 其它

SnipperImages(Silverlight DEMO)控件设计之--Slider和ColorSlider

2008-09-12 11:16 507 查看
上一篇文章中,介绍了CheckBox控件的开发方式,包括xaml和控件逻辑(cs代码控制xaml中UI元素)。

本文所要介绍的Slider控件在xaml上与CheckBox复杂度相似,比较底。而控件逻辑相对要复杂不少,这些

逻辑会在本文中进行介绍。


好了,开始今天的正文。


首先看一下这个演示页,如下:



  注:因为我从网上所获得的源码中Slider控件并没有全部开发完,起码在上面所示的垂直Slider只是粗

略的定义了xaml(其中某些值还有错误),而CS代码就少得更多了。本人在原有代码基础上,完成了垂直

Slider的开发,并修正了原有的CS代码中的BUG。


而该控件的xaml代码如下所示(Slider.xaml):

<ControlTemplate xmlns="http://schemas.microsoft.com/client/2007"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >

<Grid x:Name="Part_Root" Width="200" Height="24">

<Canvas x:Name="Part_Border" Background="Transparent">

<Line x:Name='Part_Line' StrokeThickness="1" Stroke="Blue" X1="4" X2="196" Y1="12"

Y2="12"/>

<Path x:Name='Part_ThumbHorizontal' Canvas.Top='3' Data='M0,0 L16,0 L8,18z' Fill='Silver'

Stroke='Black'/>

<Path x:Name='Part_ThumbVertical' Canvas.Left='3' Visibility="Collapsed"

Data='M0,0 L18,8 L0,16z' Fill='Silver' Stroke='Black'/>

</Canvas>

</Grid>

</ControlTemplate>

从上面代码可以看出,Slider由四个主要元素组成:

   Part_Border:用于绘制背景色(如ColorSlider控件的背景色)

Part_Line:用于绘制滑动的中线

Part_ThumbHorizontal:用于绘制水平滑块

Part_ThumbVertical:用于绘制垂直滑块

  下面这张图标识了各元素在控件中的对应位置和关系:







对应上图,下面是ColorSlider的xaml代码:

<ControlTemplate xmlns="http://schemas.microsoft.com/client/2007"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >

<Grid x:Name="Part_Root" Width='200' Height='24'>

<Canvas x:Name='Part_Border'>

<Canvas.Background>

<LinearGradientBrush x:Name="GradientBrush" StartPoint="0,0" EndPoint="1,0">

<GradientStop Color="#FF000000" Offset="0"/>

<GradientStop Color="#FFFF0000" Offset="0.143"/>

<GradientStop Color="#FF00FF00" Offset="0.286"/>

<GradientStop Color="#FF0000FF" Offset="0.429"/>

<GradientStop Color="#FF00FFFF" Offset="0.571"/>

<GradientStop Color="#FFFF00FF" Offset="0.714"/>

<GradientStop Color="#FFFFFF00" Offset="0.857"/>

<GradientStop Color="#FFFFFFFF" Offset="1"/>

</LinearGradientBrush>

</Canvas.Background>

<Line x:Name='Part_Line' StrokeThickness="1" Stroke="Blue" X1="4" X2="196" Y1="12" Y2="12"/>

<Path x:Name='Part_ThumbHorizontal' Canvas.Top='3' Data='M0,0 L16,0 L8,18z' Fill='Silver'

       Stroke='Black'/>

<Path x:Name='Part_ThumbVertical' Canvas.Left='3' Visibility="Collapsed"

       Data='M0,0 L18,8 L0,16z' Fill='Silver' Stroke='Black'/>

</Canvas>

</Grid>

</ControlTemplate>


说完了xaml,下面开始介绍cs控件逻辑代码。


首先要说的是一个枚举类型,用于标识滑动方向(垂直或水平):

/// <summary>

/// 滑动条方向类型

/// </summary>

public enum SliderOrientation

{

/// <summary>

/// 垂直

/// </summary>

Vertical,

/// <summary>

/// 水平

/// </summary>

Horizontal

}


而控件的核心代码如下(有关我修改或添加的部分已通过注释说明):

/// <summary>

/// 滑动条控制类

/// </summary>

[TemplatePart(Name = "Part_Root", Type = typeof(Panel))]

[TemplatePart(Name = "Part_Border", Type = typeof(FrameworkElement))]

[TemplatePart(Name = "Part_ThumbHorizontal", Type = typeof(FrameworkElement))]

[TemplatePart(Name = "Part_ThumbVertical", Type = typeof(FrameworkElement))]

[TemplatePart(Name = "Part_Line", Type = typeof(FrameworkElement))]

public partial class Slider : Control

{

public Slider()

{

string xaml = ResourceHelper.GetTemplate(this.GetType());

ControlTemplate template = (ControlTemplate)XamlReader.Load(xaml);

this.Template = template;

this.ApplyTemplate();

}

public event EventHandler ValueChanged;

/// <summary>

/// 值改变时

/// </summary>

protected void OnValueChanged()

{

if (ValueChanged != null)

{

//执行绑定代码

ValueChanged(this, new EventArgs());

}

}

/// <summary>

/// 绑定模板元素及相应事件

/// </summary>

public override void OnApplyTemplate()

{

Part_Root = (Panel)GetTemplateChild("Part_Root");

Part_Line = (Line)GetTemplateChild("Part_Line");

Part_ThumbHorizontal = (FrameworkElement)GetTemplateChild("Part_ThumbHorizontal");

Part_ThumbVertical = (FrameworkElement)GetTemplateChild("Part_ThumbVertical");

Part_Border = (FrameworkElement)GetTemplateChild("Part_Border");

Part_ThumbHorizontal.MouseLeftButtonDown += new MouseButtonEventHandler(Part_Thumb_MouseLeftButtonDown);

Part_ThumbHorizontal.MouseMove += new MouseEventHandler(Part_Thumb_MouseMove);

Part_ThumbHorizontal.MouseLeftButtonUp += new MouseButtonEventHandler(Part_Thumb_MouseLeftButtonUp);

Part_ThumbVertical.MouseLeftButtonDown += new MouseButtonEventHandler(Part_Thumb_MouseLeftButtonDown);

Part_ThumbVertical.MouseMove += new MouseEventHandler(Part_Thumb_MouseMove);

Part_ThumbVertical.MouseLeftButtonUp += new MouseButtonEventHandler(Part_Thumb_MouseLeftButtonUp);

Part_Root.MouseLeave += new MouseEventHandler(Part_Root_MouseLeave);

Part_Root.MouseEnter += new MouseEventHandler(Part_Root_MouseEnter);

Part_Border.MouseLeftButtonDown += new MouseButtonEventHandler(Part_Border_MouseLeftButtonDown);

}

/// <summary>

/// 当鼠标在滑动条(不是滑块)上点击时,将滑块设置到鼠标点击位置

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void Part_Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

{

//当不是滑块时

if (e.Source != Part_ThumbHorizontal && e.Source != Part_ThumbVertical)

{

Point newPos = e.GetPosition(Part_Root);

{

if (_orientation == SliderOrientation.Horizontal)

{

Part_ThumbHorizontal.SetValue(Canvas.LeftProperty, Math.Min(newPos.X,

     Part_Border.ActualWidth - Part_ThumbHorizontal.ActualWidth));

}

else

{

Part_ThumbVertical.SetValue(Canvas.TopProperty, Math.Min(newPos.Y,

     Part_Border.ActualHeight - Part_ThumbVertical.ActualHeight));

}

this.OnValueChanged();

}

}

}

/// <summary>

/// 鼠标进入滑动条区域

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void Part_Root_MouseEnter(object sender, MouseEventArgs e)

{

if (hasCapture)

{

if (_orientation == SliderOrientation.Horizontal)

{

Part_ThumbHorizontal.CaptureMouse();

}

else

{

Part_ThumbVertical.CaptureMouse();

}

}

else

{

_mouseDownValue = -1;

}

}

/// <summary>

/// 鼠标离开滑动条区域

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void Part_Root_MouseLeave(object sender, MouseEventArgs e)

{

if (_orientation == SliderOrientation.Horizontal)

{

Part_ThumbHorizontal.ReleaseMouseCapture();

}

else

{

Part_ThumbVertical.ReleaseMouseCapture();

}

}

/// <summary>

/// 鼠标按下滑动块

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void Part_Thumb_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

{

FrameworkElement thumb = (FrameworkElement)sender;

//在当前滑动块上设置“鼠标捕获”

thumb.CaptureMouse();

hasCapture = true;

_thumbMouseDown = e.GetPosition(Part_Root);



if (_orientation == SliderOrientation.Horizontal)//当为水平方向时

{

//获取滑动块的“左”值属性

_mouseDownValue = (double)thumb.GetValue(Canvas.LeftProperty);

}

else

{

//获取滑动块的“顶”值属性

_mouseDownValue = (double)thumb.GetValue(Canvas.TopProperty);

}

}

/// <summary>

/// 鼠标拖动滑动块移动

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void Part_Thumb_MouseMove(object sender, MouseEventArgs e)

{

FrameworkElement thumb = (FrameworkElement)sender;

Point newPos = e.GetPosition(Part_Root);

if (_orientation == SliderOrientation.Horizontal)

{

double newX = newPos.X - _thumbMouseDown.X + _mouseDownValue;

if (_mouseDownValue != -1 &&

newX <= Part_Border.ActualWidth - 8 &&

newX >= -8)

{

thumb.SetValue(Canvas.LeftProperty, newX);//仅在水平方向上移动

this.OnValueChanged();

}

}

else

{

double newY = newPos.Y - _thumbMouseDown.Y + _mouseDownValue;

if (_mouseDownValue != -1 &&

newY <= Part_Border.ActualHeight - 8 &&

newY >= -8)

{

thumb.SetValue(Canvas.TopProperty, newY);//仅在垂直方向上移动

this.OnValueChanged();

}

}

}

/// <summary>

/// 鼠标拖动结束

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void Part_Thumb_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)

{

FrameworkElement thumb = (FrameworkElement)sender;

_mouseDownValue = -1;

thumb.ReleaseMouseCapture();

hasCapture = false;

}

/// <summary>

/// 设置滑动条的宽

/// </summary>

public double SliderWidth

{

get { return Part_Root.Width; }

set

{

if (_orientation == SliderOrientation.Horizontal)

{

//水平方向上设置

Part_Line.X2 = value;

Part_Root.Width = value;

}

else

{

//获取Slider.xaml中的相应属性配置

Part_Line.X1 = Part_Line.X2 = value / 2d;

Part_ThumbVertical.SetValue(Canvas.LeftProperty, value / 2d - Part_ThumbVertical.ActualWidth / 2d);

}

}

}

/// <summary>

/// 设置滑动条的高度

/// </summary>

public double SliderHeight

{

get { return Part_Root.Height; }

set

{

if (_orientation == SliderOrientation.Horizontal)

{

//获取Slider.xaml中的相应属性配置

Part_Line.Y1 = Part_Line.Y2 = value / 2d;

Part_ThumbHorizontal.SetValue(Canvas.TopProperty, value / 2d - Part_ThumbHorizontal.ActualHeight / 2d);

}

else

{

//垂直方向上设置

Part_Line.Y2 = value;

Part_Root.Height = value;

}

}

}

/// <summary>

/// 获取或设置滑动条的当前值

/// </summary>

public double Value

{

get

{

if (_orientation == SliderOrientation.Horizontal)

{

double val = (double)Part_ThumbHorizontal.GetValue(Canvas.LeftProperty) / (Part_Root.ActualWidth - 8);

val = Math.Max(0d, val);

val = Math.Min(val, 1d);

return val;

}

else

{

double val = (double)Part_ThumbVertical.GetValue(Canvas.TopProperty) / (Part_Root.ActualHeight - 8);

val = Math.Max(0d, val);

val = Math.Min(val, 1d);

return val;

}

}

set

{

if (_orientation == SliderOrientation.Horizontal)

{

Part_ThumbHorizontal.SetValue(Canvas.LeftProperty, value * (Part_Root.Width - 8));

}

else

{

Part_ThumbVertical.SetValue(Canvas.TopProperty, value * (Part_Root.Height - 8));

}

}

}

/// <summary>

/// 获取或设置滑动条的方向,参见SliderOrientation

/// </summary>

public SliderOrientation Orientation

{

get { return _orientation; }

set

{

_orientation = value;

if (_orientation == SliderOrientation.Horizontal)

{

Part_ThumbVertical.Visibility = Visibility.Collapsed;

Part_ThumbHorizontal.Visibility = Visibility.Visible;

Part_Line.Y1 = Part_Line.Y2 = Part_Root.Height / 2d;

Part_Line.X1 = 0d;

Part_Line.X2 = Part_Root.Width;

}

else

{

//注:此处代码为本人所加,用于当为垂直方向时,交换Width与Height的值

double temp = Part_Root.Width;

Part_Root.Width = Part_Root.Height;

Part_Root.Height = temp;

Part_ThumbHorizontal.Visibility = Visibility.Collapsed;

Part_ThumbVertical.Visibility = Visibility.Visible;

Part_Line.X1 = Part_Line.X2 = Part_Root.Width / 2d;

Part_Line.Y1 = 0d;

Part_Line.Y2 = Part_Root.Height;

}

}

}

#region UI元素声明

protected Panel Part_Root;

protected Line Part_Line;

protected FrameworkElement Part_Border, Part_ThumbVertical, Part_ThumbHorizontal;

#endregion

protected Point _thumbMouseDown;

protected double _mouseDownValue = -1;

protected bool hasCapture = false;

protected SliderOrientation _orientation = SliderOrientation.Horizontal;

}


下面代介绍的是ColorSlider控件的控件逻辑cs文件(详情看注释):

/// <summary>

/// 颜色滑动条控制

/// </summary>

public partial class ColorSlider : Slider

{

public ColorSlider()

{

string xaml = ResourceHelper.GetTemplate(this.GetType());

ControlTemplate template = (ControlTemplate)XamlReader.Load(xaml);

this.Template = template;

base.ApplyTemplate();

}

/// <summary>

/// 该方法为本人所加,用户当滑动条方向为“垂直”时,重新设置“GradientBrush”的“EndPoint”属性

/// </summary>

public new SliderOrientation Orientation

{

get { return base.Orientation; }

set

{

base.Orientation = value;

//当为垂直方向时

if (value == SliderOrientation.Vertical)

{

((LinearGradientBrush)GetTemplateChild("GradientBrush")).EndPoint = new Point(0, 1);

}

}

}



/// <summary>

/// 获取颜色值

/// </summary>

/// <returns></returns>

public Color GetColor()

{

return this.GetColor(255);

}

/// <summary>

/// 将滑动条值(Value)转换为ARGB 颜色值并返回

/// </summary>

/// <param name="alpha">alpha通道,该值介于0到255</param>

/// <returns>ARGB 颜色值</returns>

public Color GetColor(byte alpha)

{

Color color;

double value = this.Value;

// 将滑动条的值转换为 ARGB 颜色值

if (value < 0.143d)

{

color = Color.FromArgb(alpha, (byte)Math.Floor((value * 256d) / 0.143d), 0, 0);

}

else if (value < 0.286d)

{

color = Color.FromArgb(alpha, (byte)Math.Floor(256d * (0.286d - value) / 0.143d),

(byte)Math.Floor(256d * (value - 0.143d) / 0.143d), 0);

}

else if (value < 0.429)

{

color = Color.FromArgb(alpha, 0, (byte)Math.Floor(256d * (0.429d - value) / 0.143d),

(byte)Math.Floor(256d * (value - 0.286d) / 0.143d));

}

else if (value < 0.571)

{

color = Color.FromArgb(alpha, 0, (byte)Math.Floor(256d*(value-0.429d)/0.143d), 255);

}

else if (value < 0.714)

{

color = Color.FromArgb(alpha, (byte)Math.Floor(256d * (value - 0.571d) / 0.143d),

(byte)Math.Floor(256d * (0.714d - value) / 0.143d), 255);

}

else if (value < 0.857)

{

color = Color.FromArgb(alpha, 255, (byte)Math.Floor(256d * (value - 0.714d) / 0.143d),

(byte)Math.Floor(256d * (0.857d - value) / 0.143d));

}

else

{

color = Color.FromArgb(alpha, 255, 255, (byte)Math.Floor(256d * (value - 0.857d) / 0.143d));

}

return color;

}

}


接着再来看一下如何使用这两个控件(也就是本文第一张图所演示的效果),其page逻辑代码如下:

public partial class Page2 : UserControl

{

public Page2()

{

InitializeComponent();








#region Slider测试代码,加载图片并添加演示缩放旋转的Transform

string baseUri = Application.Current.Host.Source.AbsoluteUri.Substring(0,

Application.Current.Host.Source.AbsoluteUri.LastIndexOf("/"));

currentImage.SetValue(Image.SourceProperty, new BitmapImage(

new Uri(String.Concat(baseUri, "/../Images/j0433157.jpg"))));

TransformGroup transforms = new TransformGroup();

transforms.Children.Add(new ScaleTransform());

transforms.Children.Add(new RotateTransform());

currentImage.RenderTransform = transforms;

currentImage.RenderTransformOrigin = new Point(0.5, 0.5);

#endregion

}

#region Slider示例代码

void ColorSlider_ValueChanged(object sender, EventArgs e)

{

  //水平Slider设置背景色

SliderPanel.Background = new SolidColorBrush(ColorSlider.GetColor());

}

void ColorSlider2_ValueChanged(object sender, EventArgs e)

{

  //垂直Slider设置背景色

SliderPanel2.Background = new SolidColorBrush(ColorSlider2.GetColor());

}

private void opacitySlider_ValueChanged(object sender, EventArgs e)

{ 

  //设置图像的Opacity属性

currentImage.Opacity = 1d - opacitySlider.Value;

}



private void transformSlider_ValueChanged(object sender, EventArgs e)

{

  //设置旋转属性

((RotateTransform)((TransformGroup)currentImage.RenderTransform).Children[1]).Angle =

(transformSlider.Value - 0.5d) * 720d;

//设置缩放属性

((ScaleTransform)((TransformGroup)currentImage.RenderTransform).Children[0]).ScaleX =

transformSlider.Value * 2d;

((ScaleTransform)((TransformGroup)currentImage.RenderTransform).Children[0]).ScaleY =

transformSlider.Value * 2d;

}

#endregion

}


好了,今天的内容就先到这里了。


tag:silverlight,slider,colorslider,imagesnipper

作者:代震军,daizhj


原文链接:http://www.cnblogs.com/daizhj/archive/2008/09/04/1284228.html


源码下载,请点击这里:)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: