下面就是它的一些演示截图。
首先是缩放,旋转和透明处理:
首先是缩放,旋转和透明处理:
然后是文字水印处理:
然后是使用Ink的涂鸭:
相信做为一个相册(图片浏览)的基本功能已经没什么问题了。
下面来看一下这个DEMO的类图,如下:
上图中的左半部用红框标识的区域是其控件设计类,因为本DEMO中所使用的控件如:按钮,滑动条,复选框等均未使用Silverlight中所提供的控件,而是自己绘制并定义事件。因此这是我对该DEMO感兴趣的另一个原因。而右侧则是一些工具类或图片处理类,如处理图片移动的MovableImage和TextBlock移动的
MovableTextBlock等。
下面先简要介绍一下其中的Button按钮控件的设计思路。因为其继承自ButtonBase,所以有必要先看一下ButtonBase的代码声明,下面是xaml中的内容:
<
ControlTemplate
xmlns
="http://schemas.microsoft.com/client/2007"
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" >
< Grid x:Name ="Part_Root" MouseEnter ="btnClearMouseEnter" MouseLeave ="btnClearMouseLeave"
MouseLeftButtonDown ="btnClearMouseDown" MouseLeftButtonUp ="btnClearMouseUp" >
< Grid.Resources >
< Storyboard x:Name ="Part_MouseEnter" />
< Storyboard x:Name ="Part_MouseDown" />
< Storyboard x:Name ="Part_MouseUp" />
< Storyboard x:Name ="Part_MouseLeave" />
</ Grid.Resources >
< Rectangle x:Name ="Part_BackgroundRect" />
< TextBlock x:Name ="Part_Caption" />
< Rectangle x:Name ="Part_ForegroundRect" />
< Rectangle x:Name ="Part_HighlightRect" />
</ Grid >
</ ControlTemplate >
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" >
< Grid x:Name ="Part_Root" MouseEnter ="btnClearMouseEnter" MouseLeave ="btnClearMouseLeave"
MouseLeftButtonDown ="btnClearMouseDown" MouseLeftButtonUp ="btnClearMouseUp" >
< Grid.Resources >
< Storyboard x:Name ="Part_MouseEnter" />
< Storyboard x:Name ="Part_MouseDown" />
< Storyboard x:Name ="Part_MouseUp" />
< Storyboard x:Name ="Part_MouseLeave" />
</ Grid.Resources >
< Rectangle x:Name ="Part_BackgroundRect" />
< TextBlock x:Name ="Part_Caption" />
< Rectangle x:Name ="Part_ForegroundRect" />
< Rectangle x:Name ="Part_HighlightRect" />
</ Grid >
</ ControlTemplate >
从上面代码可以看出其采用控件模版的方式进行定义。但其鼠标在按钮上移入移出等状态的Storyboard(故事板)并未进行定义。而肯体的实现被放在了相应的子类(Button.xaml和RepeatButton.xaml)进行实现。下面就是其中的Button.xaml内容:
<
ControlTemplate
xmlns
="http://schemas.microsoft.com/client/2007"
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" >
< Grid x:Name ="Part_Root" MouseEnter ="btnClearMouseEnter" MouseLeave ="btnClearMouseLeave"
MouseLeftButtonDown ="btnClearMouseDown" MouseLeftButtonUp ="btnClearMouseUp" >
< Grid.Resources >
< Storyboard x:Name ="Part_MouseEnter" >
< ColorAnimation Duration ="00:00:00.25" To ="#3DFFFFFF" Storyboard.TargetName ="Part_HighlightRect"
Storyboard.TargetProperty ="(Shape.Fill).(SolidColorBrush.Color)" />
</ Storyboard >
< Storyboard x:Name ="Part_MouseDown" >
< ColorAnimation Duration ="00:00:00.2" To ="#22000000" Storyboard.TargetName ="Part_HighlightRect"
Storyboard.TargetProperty ="(Shape.Fill).(SolidColorBrush.Color)" />
</ Storyboard >
< Storyboard x:Name ="Part_MouseUp" >
< ColorAnimation Duration ="00:00:00.2" To ="#3DFFFFFF" Storyboard.TargetName ="Part_HighlightRect"
Storyboard.TargetProperty ="(Shape.Fill).(SolidColorBrush.Color)" />
</ Storyboard >
< Storyboard x:Name ="Part_MouseLeave" >
< ColorAnimation Duration ="00:00:00.25" To ="#00FFFFFF" Storyboard.TargetName ="Part_HighlightRect"
Storyboard.TargetProperty ="(Shape.Fill).(SolidColorBrush.Color)" />
</ Storyboard >
</ Grid.Resources >
< Rectangle x:Name ="Part_BackgroundRect" StrokeThickness ="4" RadiusX ="16" RadiusY ="36" Stroke ="#46000000" >
< Rectangle.Fill >
< LinearGradientBrush EndPoint ="0.5,-0.4" StartPoint ="0.5,1.4" >
< GradientStop Color ="Gray" Offset ="0.242" />
< GradientStop Color ="DarkBlue" Offset ="0.333" />
</ LinearGradientBrush >
</ Rectangle.Fill >
</ Rectangle >
< TextBlock x:Name ="Part_Caption" VerticalAlignment ="Center" HorizontalAlignment ="Center"
Foreground ="Gold" Text ="Button" >
< TextBlock.RenderTransform >
< TranslateTransform X ="0" Y ="-2" />
</ TextBlock.RenderTransform >
</ TextBlock >
< Rectangle x:Name ="Part_ForegroundRect" VerticalAlignment ="Top" StrokeThickness ="4" RadiusX ="16"
RadiusY ="36" Width ="124" Height ="32" >
< Rectangle.Fill >
< LinearGradientBrush EndPoint ="0.5,-0.409" StartPoint ="0.5,1.409" >
< GradientStop Color ="#00FFFFFF" Offset ="0.13" />
< GradientStop Color ="#FFFFFFFF" Offset ="1" />
</ LinearGradientBrush >
</ Rectangle.Fill >
</ Rectangle >
< Rectangle VerticalAlignment ="Top" RadiusX ="16" RadiusY ="36" Fill ="#00FFFFFF" x:Name ="Part_HighlightRect" />
</ Grid >
</ ControlTemplate >
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" >
< Grid x:Name ="Part_Root" MouseEnter ="btnClearMouseEnter" MouseLeave ="btnClearMouseLeave"
MouseLeftButtonDown ="btnClearMouseDown" MouseLeftButtonUp ="btnClearMouseUp" >
< Grid.Resources >
< Storyboard x:Name ="Part_MouseEnter" >
< ColorAnimation Duration ="00:00:00.25" To ="#3DFFFFFF" Storyboard.TargetName ="Part_HighlightRect"
Storyboard.TargetProperty ="(Shape.Fill).(SolidColorBrush.Color)" />
</ Storyboard >
< Storyboard x:Name ="Part_MouseDown" >
< ColorAnimation Duration ="00:00:00.2" To ="#22000000" Storyboard.TargetName ="Part_HighlightRect"
Storyboard.TargetProperty ="(Shape.Fill).(SolidColorBrush.Color)" />
</ Storyboard >
< Storyboard x:Name ="Part_MouseUp" >
< ColorAnimation Duration ="00:00:00.2" To ="#3DFFFFFF" Storyboard.TargetName ="Part_HighlightRect"
Storyboard.TargetProperty ="(Shape.Fill).(SolidColorBrush.Color)" />
</ Storyboard >
< Storyboard x:Name ="Part_MouseLeave" >
< ColorAnimation Duration ="00:00:00.25" To ="#00FFFFFF" Storyboard.TargetName ="Part_HighlightRect"
Storyboard.TargetProperty ="(Shape.Fill).(SolidColorBrush.Color)" />
</ Storyboard >
</ Grid.Resources >
< Rectangle x:Name ="Part_BackgroundRect" StrokeThickness ="4" RadiusX ="16" RadiusY ="36" Stroke ="#46000000" >
< Rectangle.Fill >
< LinearGradientBrush EndPoint ="0.5,-0.4" StartPoint ="0.5,1.4" >
< GradientStop Color ="Gray" Offset ="0.242" />
< GradientStop Color ="DarkBlue" Offset ="0.333" />
</ LinearGradientBrush >
</ Rectangle.Fill >
</ Rectangle >
< TextBlock x:Name ="Part_Caption" VerticalAlignment ="Center" HorizontalAlignment ="Center"
Foreground ="Gold" Text ="Button" >
< TextBlock.RenderTransform >
< TranslateTransform X ="0" Y ="-2" />
</ TextBlock.RenderTransform >
</ TextBlock >
< Rectangle x:Name ="Part_ForegroundRect" VerticalAlignment ="Top" StrokeThickness ="4" RadiusX ="16"
RadiusY ="36" Width ="124" Height ="32" >
< Rectangle.Fill >
< LinearGradientBrush EndPoint ="0.5,-0.409" StartPoint ="0.5,1.409" >
< GradientStop Color ="#00FFFFFF" Offset ="0.13" />
< GradientStop Color ="#FFFFFFFF" Offset ="1" />
</ LinearGradientBrush >
</ Rectangle.Fill >
</ Rectangle >
< Rectangle VerticalAlignment ="Top" RadiusX ="16" RadiusY ="36" Fill ="#00FFFFFF" x:Name ="Part_HighlightRect" />
</ Grid >
</ ControlTemplate >
注:这样设计方式本人感觉很有意思,很有“面向对象”的味道,呵呵。
下面简要浏览一下ButtonBase.xaml.cs的代码:
下面简要浏览一下ButtonBase.xaml.cs的代码:
[TemplatePart(Name
=
"
Part_Root
"
, Type
=
typeof
(Panel))]
[TemplatePart(Name = " Part_Caption " , Type = typeof (TextBlock))]
[TemplatePart(Name = " Part_ForegroundRect " , Type = typeof (Rectangle))]
[TemplatePart(Name = " Part_BackgroundRect " , Type = typeof (Rectangle))]
[TemplatePart(Name = " Part_HighlightRect " , Type = typeof (Rectangle))]
[TemplatePart(Name = " Part_MouseEnter " , Type = typeof (Storyboard))]
[TemplatePart(Name = " Part_MouseLeave " , Type = typeof (Storyboard))]
[TemplatePart(Name = " Part_MouseDown " , Type = typeof (Storyboard))]
[TemplatePart(Name = " Part_MouseUp " , Type = typeof (Storyboard))]
public abstract partial class ButtonBase : Control
{
/// <summary>
/// 定义单击事件
/// </summary>
public event EventHandler Click;
/// <summary>
/// 执行单击事件的绑定方法
/// </summary>
protected void OnClick()
{
if (Click != null )
{
Click( this , new EventArgs());
}
}
/// <summary>
/// 标题属性
/// </summary>
public string Caption
{
get { return this .Part_Caption.Text; }
set { this .Part_Caption.Text = value; }
}
/// <summary>
/// 鼠标移入控件区域时启动Part_MouseEnter故事板,下面类似
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void Part_Root_MouseEnter( object sender, MouseEventArgs e)
{
Part_MouseEnter.Begin();
}
protected virtual void Part_Root_MouseLeave( object sender, MouseEventArgs e)
{
Part_MouseLeave.Begin();
}
protected virtual void Part_Root_MouseLeftButtonDown( object sender, MouseButtonEventArgs e)
{
Part_MouseDown.Begin();
}
protected virtual void Part_Root_MouseLeftButtonUp( object sender, MouseButtonEventArgs e)
{
Part_MouseUp.Begin();
// 执行单击事件的绑定方法
OnClick();
}
protected Storyboard Part_MouseEnter, Part_MouseDown, Part_MouseLeave, Part_MouseUp;
protected Rectangle Part_ForegroundRect, Part_BackgroundRect, Part_HighlightRect;
protected Panel Part_Root;
protected TextBlock Part_Caption;
}
[TemplatePart(Name = " Part_Caption " , Type = typeof (TextBlock))]
[TemplatePart(Name = " Part_ForegroundRect " , Type = typeof (Rectangle))]
[TemplatePart(Name = " Part_BackgroundRect " , Type = typeof (Rectangle))]
[TemplatePart(Name = " Part_HighlightRect " , Type = typeof (Rectangle))]
[TemplatePart(Name = " Part_MouseEnter " , Type = typeof (Storyboard))]
[TemplatePart(Name = " Part_MouseLeave " , Type = typeof (Storyboard))]
[TemplatePart(Name = " Part_MouseDown " , Type = typeof (Storyboard))]
[TemplatePart(Name = " Part_MouseUp " , Type = typeof (Storyboard))]
public abstract partial class ButtonBase : Control
{
/// <summary>
/// 定义单击事件
/// </summary>
public event EventHandler Click;
/// <summary>
/// 执行单击事件的绑定方法
/// </summary>
protected void OnClick()
{
if (Click != null )
{
Click( this , new EventArgs());
}
}
/// <summary>
/// 标题属性
/// </summary>
public string Caption
{
get { return this .Part_Caption.Text; }
set { this .Part_Caption.Text = value; }
}
/// <summary>
/// 鼠标移入控件区域时启动Part_MouseEnter故事板,下面类似
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void Part_Root_MouseEnter( object sender, MouseEventArgs e)
{
Part_MouseEnter.Begin();
}
protected virtual void Part_Root_MouseLeave( object sender, MouseEventArgs e)
{
Part_MouseLeave.Begin();
}
protected virtual void Part_Root_MouseLeftButtonDown( object sender, MouseButtonEventArgs e)
{
Part_MouseDown.Begin();
}
protected virtual void Part_Root_MouseLeftButtonUp( object sender, MouseButtonEventArgs e)
{
Part_MouseUp.Begin();
// 执行单击事件的绑定方法
OnClick();
}
protected Storyboard Part_MouseEnter, Part_MouseDown, Part_MouseLeave, Part_MouseUp;
protected Rectangle Part_ForegroundRect, Part_BackgroundRect, Part_HighlightRect;
protected Panel Part_Root;
protected TextBlock Part_Caption;
}
其实上面的代码与我们平时写.net控件类似,也是属性事件的定义。当然不同的地方就是对故事板的使用,
而故事板会让我们的按钮在鼠标触发事件时在UI上看起来更酷。当然下面还要看一下相应的Button中的内容,因
为这才是实际运行时使用的控件,其代码如下:
而故事板会让我们的按钮在鼠标触发事件时在UI上看起来更酷。当然下面还要看一下相应的Button中的内容,因
为这才是实际运行时使用的控件,其代码如下:
public
partial
class
Button : ButtonBase
{
public Button()
{
// 加载Button.xaml中的内容,为下面获取元素进行相应操作
string xaml = ResourceHelper.GetTemplate( this .GetType());
ControlTemplate template = (ControlTemplate)XamlReader.Load(xaml);
this .Template = template;
this .ApplyTemplate();
}
/// <summary>
/// 对当前模板(xaml)中的元素进行(主要是鼠标)事件绑定
/// </summary>
public override void OnApplyTemplate()
{
Part_Root = (Panel)GetTemplateChild( " Part_Root " );
Part_Caption = (TextBlock)GetTemplateChild( " Part_Caption " );
Part_ForegroundRect = (Rectangle)GetTemplateChild( " Part_ForegroundRect " );
Part_BackgroundRect = (Rectangle)GetTemplateChild( " Part_BackgroundRect " );
Part_HighlightRect = (Rectangle)GetTemplateChild( " Part_HighlightRect " );
Part_MouseEnter = (Storyboard)GetTemplateChild( " Part_MouseEnter " );
Part_MouseLeave = (Storyboard)GetTemplateChild( " Part_MouseLeave " );
Part_MouseDown = (Storyboard)GetTemplateChild( " Part_MouseDown " );
Part_MouseUp = (Storyboard)GetTemplateChild( " Part_MouseUp " );
Part_Root.SizeChanged += new SizeChangedEventHandler(Part_Root_SizeChanged);
Part_Root.MouseEnter += new MouseEventHandler(Part_Root_MouseEnter);
Part_Root.MouseLeave += new MouseEventHandler(Part_Root_MouseLeave);
Part_Root.MouseLeftButtonDown += new MouseButtonEventHandler(Part_Root_MouseLeftButtonDown);
Part_Root.MouseLeftButtonUp += new MouseButtonEventHandler(Part_Root_MouseLeftButtonUp);
}
/// <summary>
/// 按钮的实际高度或宽度发生变化时的处理事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void Part_Root_SizeChanged( object sender, SizeChangedEventArgs e)
{
Part_ForegroundRect.Width = Part_Root.ActualWidth - 16d;
Part_ForegroundRect.Height = Part_Root.ActualHeight - 12d;
Part_HighlightRect.Width = Part_Root.ActualWidth - 10d;
Part_HighlightRect.Height = Part_Root.ActualHeight - 8d;
if (Part_Root.ActualWidth > Part_Root.ActualHeight)
{
Part_BackgroundRect.RadiusX = Part_ForegroundRect.RadiusX = Part_HighlightRect.RadiusX =
Part_Root.ActualHeight / 2d;
Part_BackgroundRect.RadiusY = Part_ForegroundRect.RadiusY = Part_HighlightRect.RadiusY =
Part_Root.ActualWidth / 4d;
}
else
{
Part_BackgroundRect.RadiusX = Part_ForegroundRect.RadiusX = Part_HighlightRect.RadiusX =
Part_Root.ActualHeight / 4d;
Part_BackgroundRect.RadiusY = Part_ForegroundRect.RadiusY = Part_HighlightRect.RadiusY =
Part_Root.ActualWidth / 2d;
}
}
}
{
public Button()
{
// 加载Button.xaml中的内容,为下面获取元素进行相应操作
string xaml = ResourceHelper.GetTemplate( this .GetType());
ControlTemplate template = (ControlTemplate)XamlReader.Load(xaml);
this .Template = template;
this .ApplyTemplate();
}
/// <summary>
/// 对当前模板(xaml)中的元素进行(主要是鼠标)事件绑定
/// </summary>
public override void OnApplyTemplate()
{
Part_Root = (Panel)GetTemplateChild( " Part_Root " );
Part_Caption = (TextBlock)GetTemplateChild( " Part_Caption " );
Part_ForegroundRect = (Rectangle)GetTemplateChild( " Part_ForegroundRect " );
Part_BackgroundRect = (Rectangle)GetTemplateChild( " Part_BackgroundRect " );
Part_HighlightRect = (Rectangle)GetTemplateChild( " Part_HighlightRect " );
Part_MouseEnter = (Storyboard)GetTemplateChild( " Part_MouseEnter " );
Part_MouseLeave = (Storyboard)GetTemplateChild( " Part_MouseLeave " );
Part_MouseDown = (Storyboard)GetTemplateChild( " Part_MouseDown " );
Part_MouseUp = (Storyboard)GetTemplateChild( " Part_MouseUp " );
Part_Root.SizeChanged += new SizeChangedEventHandler(Part_Root_SizeChanged);
Part_Root.MouseEnter += new MouseEventHandler(Part_Root_MouseEnter);
Part_Root.MouseLeave += new MouseEventHandler(Part_Root_MouseLeave);
Part_Root.MouseLeftButtonDown += new MouseButtonEventHandler(Part_Root_MouseLeftButtonDown);
Part_Root.MouseLeftButtonUp += new MouseButtonEventHandler(Part_Root_MouseLeftButtonUp);
}
/// <summary>
/// 按钮的实际高度或宽度发生变化时的处理事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void Part_Root_SizeChanged( object sender, SizeChangedEventArgs e)
{
Part_ForegroundRect.Width = Part_Root.ActualWidth - 16d;
Part_ForegroundRect.Height = Part_Root.ActualHeight - 12d;
Part_HighlightRect.Width = Part_Root.ActualWidth - 10d;
Part_HighlightRect.Height = Part_Root.ActualHeight - 8d;
if (Part_Root.ActualWidth > Part_Root.ActualHeight)
{
Part_BackgroundRect.RadiusX = Part_ForegroundRect.RadiusX = Part_HighlightRect.RadiusX =
Part_Root.ActualHeight / 2d;
Part_BackgroundRect.RadiusY = Part_ForegroundRect.RadiusY = Part_HighlightRect.RadiusY =
Part_Root.ActualWidth / 4d;
}
else
{
Part_BackgroundRect.RadiusX = Part_ForegroundRect.RadiusX = Part_HighlightRect.RadiusX =
Part_Root.ActualHeight / 4d;
Part_BackgroundRect.RadiusY = Part_ForegroundRect.RadiusY = Part_HighlightRect.RadiusY =
Part_Root.ActualWidth / 2d;
}
}
}
到这里还有另一个按钮控件RepeatButton没有介绍,其实它的内容也上面的Button代码相似,所以就不多介绍了。
当然RepeatButton最终的用处是被放在了ImageSelector控件中做为子控制被加载,这其中与我们开发“复合型”控件
相似。
下面就是Button控制的运行效果,如下所示:
当然这个DEMO在控件开发上还有一些有特色的地方,比如CheckBox控件等,我会在接下来的文章中加以说明,
呵呵。
好了,今天的内容就先到这里了。
本文转自 daizhenjun 51CTO博客,原文链接:http://blog.51cto.com/daizhj/100970,如需转载请自行联系原作者