专栏首页张善友的专栏[翻译]开发Silverlight 2.0的自定义控件

[翻译]开发Silverlight 2.0的自定义控件

原文:Developing a Custom Control for Silverlight 2.0

译者:张善友

介绍

这篇文章主要展示了你制作一个Silverlight 2.0的自定义空间需要哪些步骤和在你的Silverlight项目中重用代码。

本文基于Mix08上发布的Silverlight 2.0 beta1。

文章中我会创建一个控件库和实现自定义控件按钮类,没有任何新增功能只是继承缺省Button类,但是带一个不同原来的button的缺省样式。重用这个控件你不需要为你的项目中的所有控件实例添加Style属性。

让我们开始吧

创建项目

使用Visual Studio 2008新建一个Silerlight 类库项目。

因为这是一个控件库,我们要添加程序集System.Windows.Controls的引用,这个程序集在Silverlight 2.0 beta 1的版本号是1.0.0.0(不要问为什么:-) ),默认会并放在"C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Libraries\Client\System.Windows.Controls.dll"。

下一步是给我们的控件程序集加入XmlnsDefinitionAttribute

这个特性帮助XAML处理器找到和匹配Xml命名空间和CLR的命名空间,因此添加这个特性带下面的参数:

[assembly: System.Windows.Markup.XmlnsDefinition ("http://schemas.eyedea.hu/silverlight/2008/xaml/presentation", "Eyedea.Controls")]

创建控件类

解决方案内找到Class1.cs文件,利用Visual Studio的重构功能,将Class1.cs重命名为MediaButton.cs

下一步我们添加我们XAML文件,里面包含这个控件库里面的控件要使用的缺省样式。

让我们添加一个文本类型的项目到公秤里,命名为generic.xaml。

选择generic.xaml文件并设置为嵌入式资源。通过删除Custom Tool属性值并设置Build Action为Resource。

现在轮到编辑我们的主要对象:MediaButton.cs文件。打开这个文件,添加命令空间System.Windows.Controls的引用修改MediaButton类从系统内建的Button类继承。

我们的MediaButton类看起来像这个样子: 

using System.Windows.Controls;



namespace Eyedea.Controls

{

    public class MediaButton : Button

    {

            public MediaButton()

            {

            }

    }

}

给我们的控件加入默认的样式

打开文件general.xmal

首先添加下面的缺省内容到XAML文件和一个引用到我们的XML命名空间:

<ResourceDictionary 

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

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

    xmlns:local="clr-namespace:Eyedea.Controls;assembly=Eyedea.Controls">

</ResourceDictionary>

请注意local这个Xml命名空间前缀将被用于这个控件库里面控件的样式引用。

添加Style标签到我们定义样式的地方,在Style标签有个TargeType属性指定该样式将使用在哪类控件,在这里指向我们的MediaButton,你还必须和TargeType属性一样指定ControlTemplate属性

<Style TargetType="local:MediaButton">

    <Setter property="Template">

        <Setter.Value>

            <ControlTemplate TargetType="local:MediaButton">

                <Grid x:Name="RootElement">

                </Grid>

            </ControlTemplate>

        </Setter.Value>

    </Setter>

</Style>

在Style标签内可以定义充分的控件外观包括StoryBoards式的视觉状态转换,视觉元素和StoryBoards的名称非常重要,因为他们是Silverlight的样式可以工作的不可或缺的一部分,这里我们不讨论,将在另外的文章中讨论。

当前控件设计有一个固定的宽度和高度,因此我们可以通过用Setter来指定。

我们也指定控件的最小和最大尺寸以保护我们设计的按钮。

提示:简单的属性Setters应直接放在Style标签之后和在Template标签之前。

<!-- Common properties -->
<Setter property="IsEnabled" Value="true" />
<Setter property="IsTabStop" Value="true" />
<Setter property="Margin" Value="0" />
<Setter property="HorizontalContentAlignment" Value="Center" />
<Setter property="VerticalContentAlignment" Value="Center" />
<Setter property="Cursor" Value="Arrow" />
<Setter property="Foreground" Value="#CC808080" />
<!-- Text related properties -->
<Setter property="TextAlignment" Value="Left" />
<Setter property="TextWrapping" Value="NoWrap" />
<Setter property="FontSize" Value="11" />
<!-- Default Size Constraints -->
<Setter property="Width" Value="50" />
<Setter property="MinWidth" Value="50" />
<Setter property="MaxWidth" Value="50" />
<Setter property="Height" Value="22" />
<Setter property="MinHeight" Value="22" />
<Setter property="MaxHeight" Value="22" />

添加视觉元到模板可复制我们的第一次Expression Design设计的以下xaml内容的一种样式。

这个设计包含一个背景矩形,一个大纲,两个亮点将在和用户交互的时候动画显示。

在底部你发现有一个ContentPresenter元素,它是Button的Content属性的占位符。

添加下列内容到Grid标签:

<Grid.Resources>

    <Storyboard x:Key="MouseOver State">

        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightTop" Storyboard.Targetproperty="(UIElement.Opacity)">

            <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.3"/>

        </DoubleAnimationUsingKeyFrames>

        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightBottom" Storyboard.Targetproperty="(UIElement.Opacity)">

            <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>

        </DoubleAnimationUsingKeyFrames>

        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Border" Storyboard.Targetproperty="(UIElement.Opacity)">

            <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.7"/>

        </DoubleAnimationUsingKeyFrames>

    </Storyboard>

    <Storyboard x:Key="Pressed State">

        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightTop" Storyboard.Targetproperty="(UIElement.Opacity)">

            <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>

        </DoubleAnimationUsingKeyFrames>

        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightBottom" Storyboard.Targetproperty="(UIElement.Opacity)">

            <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.3"/>

        </DoubleAnimationUsingKeyFrames>

        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Border" Storyboard.Targetproperty="(UIElement.Opacity)">

            <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.5"/>

        </DoubleAnimationUsingKeyFrames>

    </Storyboard>

    <Storyboard x:Key="Normal State" />

    <Storyboard x:Key="Disabled State">

        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightTop" Storyboard.Targetproperty="(UIElement.Opacity)">

            <SplineDoubleKeyFrame KeyTime="00:00:00.1500000" Value="0"/>

        </DoubleAnimationUsingKeyFrames>

        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightBottom" Storyboard.Targetproperty="(UIElement.Opacity)">

            <SplineDoubleKeyFrame KeyTime="00:00:00.1500000" Value="0"/>

        </DoubleAnimationUsingKeyFrames>

        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ContentPresenter" Storyboard.Targetproperty="(UIElement.Opacity)">

            <SplineDoubleKeyFrame KeyTime="00:00:00.1500000" Value="0.7"/>

        </DoubleAnimationUsingKeyFrames>

    </Storyboard>

</Grid.Resources>

<Rectangle Fill="#FF000000" Margin="2,2,2,2" RadiusX="1" RadiusY="1" Opacity="0.3"/>

<Rectangle x:Name="Border" Stroke="#FF808080" RadiusX="2" RadiusY="2" Opacity="0.3"/>

<Path x:Name="HighlightTop" Margin="2,2,2,11" Opacity="0.2" Data="M0,1 C0,0.45 0.45,0 1,0 L45,0 C45.55,0 46,0.45 46,1 C46,1 46,9 46,9 C46,9 0,9 0,9 C0,9 0,1 0,1 z">

    <Path.Fill>

        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">

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

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

        </LinearGradientBrush>

    </Path.Fill>

</Path>

<Path x:Name="HighlightBottom" Margin="2,11,2,2" Opacity="0" Data="M0,0 C0,0 31,0 46,0 C46,0 46,8 46,8 C46,8.55 45.55,9 45,9 L1,9 C0.45,9 0,8.55 0,8 C0,8 0,0 0,0 z">

    <Path.Fill>

        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">

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

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

        </LinearGradientBrush>

    </Path.Fill>

</Path>

<ContentPresenter x:Name="ContentPresenter"

    Content="{TemplateBinding Content}"

    ContentTemplate="{TemplateBinding ContentTemplate}"

    FontFamily="{TemplateBinding FontFamily}"

    FontSize="{TemplateBinding FontSize}"

    FontStretch="{TemplateBinding FontStretch}"

    FontStyle="{TemplateBinding FontStyle}"

    FontWeight="{TemplateBinding FontWeight}"

    Foreground="{TemplateBinding Foreground}"

    HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"

    Padding="{TemplateBinding Padding}"

    TextAlignment="{TemplateBinding TextAlignment}"

    TextDecorations="{TemplateBinding TextDecorations}"

    TextWrapping="{TemplateBinding TextWrapping}"

    VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"

/>

编译工程,如果一切正常,一个自定义控件就完成了 

测试控件

要测试空间,我们需要创建一个Silverlight 应用工程。在解决方案浏览器中右击Solution节点选择添加一个Silverlight应用类型项目:

对于Silverlight应用,Visual Studio会问我们用那种方法测试Silverlight应用。为目前为止,我们选择一个HTML页面来测试比较合适。

设置TestApplication项目作为我们的启动项目,右击该项目的节点,并选择"设置为启动项目" 。

将我们控件加入测试项目

在测试项目TestApplication中测试我们的自定义控件,我们需要添加控件工程的引用。

在设计器打开Page.xaml文件并切换到XAML视图,为了在页面上使用MediaButton 控件,我们要在页面的XAMLUserControl标签中注册控件命名空间。

测试页面包含一个4乘3的网格Grid和两个MediaButton实例,内容为“Play”和“Stop”:

完成的Page.xaml内容如下:

<UserControl x:Class="TestApplication.Page"

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

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

    xmlns:eyedea="clr-namespace:Eyedea.Controls;assembly=Eyedea.Controls"

    Width="320" Height="240">

        <Grid x:Name="LayoutRoot" Background="Black" Margin="50,50,50,50">

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="*" />

                <ColumnDefinition Width="Auto"/>

                <ColumnDefinition Width="Auto"/>

                <ColumnDefinition Width="*"/>

            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>

                <RowDefinition Height="*" />

                <RowDefinition Height="Auto" />

                <RowDefinition Height="*" />

            </Grid.RowDefinitions>

            <Grid.RenderTransform>

                <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="2" ScaleY="2" />

            </Grid.RenderTransform>

            <Rectangle Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1" Stroke="#FF808080" RadiusX="2" RadiusY="2" Opacity="0.3"/>

            <eyedea:MediaButton Grid.Column="1" Grid.Row="1" Margin="2,2,2,2" Content="Play">

            </eyedea:MediaButton>

            <eyedea:MediaButton Grid.Column="2" Grid.Row="1" Margin="2,2,2,2" Content="Stop">

            </eyedea:MediaButton>

        </Grid>

</UserControl>

按F5测试控件,Silverlight2.0的键盘支持比Silverlight1.0要好得多。

下一步做什么

  • 我计划写一篇文章,我将在这篇文章知识的基础之上建立一个可更换皮肤的控件。
  • 和很多更多silverlight 2.0特性 ;-)

兴趣点

关于作者

Attila Hajdrik 之前是微软的高级顾问,2008年成立了自己的公司,公司的重点是.NET开发,主要是Silverlight 2.0和WPF项目 译者注:通过这篇文章就可以知道Silverlight 2.0的控件是怎么实现的,可以通过学习Silverlight 2.0的控件源代码来学习设计Silvelight 2.0 控件。 Silverlight 2 Beta 1 控件代码以及单元测试,下载地址: http://www.microsoft.com/downloads/details.aspx?FamilyID=EA93DD89-3AF2-4ACB-9CF4-BFE01B3F02D4&displaylang=en

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Sketchflow for Windows Phone 7

    这篇文章小试Sketchflow for Windows Phone 7 简要的介绍了Sketchflow for Windows Phone 7,这里是我主要...

    张善友
  • Windows远程桌面连接Mac OS X

    第一步:Mac OS X 10.5 已经增加支持了由VNC Viewer访问的功能,设置如下:   系统偏好设置-共享-勾选“屏幕共享”,然后在电脑设置—...

    张善友
  • Quartz.NET 1.0正式发布

    Quartz.NET 项目在Marko Lahma的领导下,经历了2年多时间的开发,bug修复和新特性开发终于发布了1.0版本,这个版本对Quartz.NET来...

    张善友
  • 打开控制台也删不掉的元素,前端都吓尿了

    运行完我的代码了,又切回element板块,想删掉它(谁叫你那么大坨的,被我盯上了)。点一下选中这个div,然后按一下删除

    lhyt
  • 浅谈矩阵的特征向量特征值的意义

    线性变换与矩阵的特征向量特征值 ? 2.数学上的意义 ? ? 3.在物理上的意义 ? ? 4.信息处理上的意义 ? 5.哲学上的意义 ?

    瓜大三哥
  • 每日一练(2017/5/17)

    Java基础 | 数据库 | Android | 学习视频 | 学习资料下载 课前导读 ●回复"每日一练"获取以前的题目! ●答案公布时间:为每期发布题目的第二...

    Java学习
  • Kaggle&TianChi分类问题相关算法快速实现导读理论解析如何设计一个Stacking|Ensemble的模型?案例复现

    17/12/30-update :很多朋友私密我想要代码,甚至利用金钱诱惑我,好吧,我沦陷了。因为原始代码涉及到公司的特征工程及一些利益trick,所以我构造了...

    sladesal
  • 【开源游戏/经营策略】宠物等你来救!

    一款将消除玩法和动物营救玩法完美结合的休闲游戏,各种场景画面做得十分精致,各种鸟叫声的运用,让音乐充满乡村园林气息,游戏中会有不同颜色的砖块。

    用户5997198
  • Python每日一题:__new__ 与 __init__

    首先,我们来看下第一个作用,比如我们有一种需求,是一直要得到大写的字符串,类似新增一种数据类型,它会一直返回字符串的大写形式。我们就可以用 __new__ 来实...

    用户7685359
  • Java程序性能优化之编程技巧总结

    程序的性能受代码质量的直接影响。在本文中,主要介绍一些代码编写的小技巧和惯例,这些技巧有助于在代码级别上提升系统性能。

    lyb-geek

扫码关注云+社区

领取腾讯云代金券