蝈蝈俊.net

-- 用随笔来记录自己的技术感触
随笔 - 655, 评论 - 4839, 引用 - 276

导航

关于

这里是我的技术Blog,下一代CSDN社区Blog在 http://blog.csdn.net/ghj1976/

标签

每月存档

最新留言

  • re:WPF/Silverlight 控件的几幅继承关系图
    <p class="MsoNormal" style="text-align: center; line-height: 20pt; margin: 0cm 0cm...
    by oaoffices(注册) on 2010/2/7 18:38:37
  • tWTqXHvjmOmv
    XZ5W2T &lt;a href=&quot;http://zecclkdejwou.com/&quot;&gt;zecclkdejwou&lt;/a&am...
    by uwwkhptujtw(匿名) on 2010/2/7 11:26:16
  • Re
    Many times we wanted to order significant example thesis close to this topic in the &lt;a href=&...
    by Ellieru(匿名) on 2010/2/6 10:25:37
  • Rrwvthsw
    Very Good Site &lt;a href=&quot; http://www.newsland.it/nr/article/it-alt.faq/4163.html &...
    by Rrwvthsw(匿名) on 2010/2/6 5:51:43
  • Edozadcx
    Good crew it's cool :) &lt;a href=&quot; http://www.newsland.it/nr/article/it-alt.faq/4163.h...
    by Edozadcx(匿名) on 2010/2/6 3:56:25
  • Ptryjfhi
    i'm fine good work &lt;a href=&quot; http://www.newsland.it/nr/article/it-alt.faq/4143.html ...
    by Ptryjfhi(匿名) on 2010/2/6 2:52:34
  • samuel
    5l05ro http://www.cRk2bdPqQls602mIa4bgo.com
    by samuel(匿名) on 2010/2/5 4:00:27
  • samuel
    5l05ro http://www.cRk2bdPqQls602mIa4bgo.com
    by samuel(匿名) on 2010/2/5 4:00:25
  • qCSFwFqaMVQizlCas
    2dnR2u &lt;a href=&quot;http://geunkaxpmhqt.com/&quot;&gt;geunkaxpmhqt&lt;/a&am...
    by spahxbypafn(匿名) on 2010/2/5 1:47:48
  • Re
    Very oft the &lt;a href=&quot;http://quality-papers.com/topics/comparison_essay&quot;&am...
    by Gwen18uV(匿名) on 2010/2/4 16:16:33
  • samuel
    SnU3S6 http://www.cRk2bdPqQls602mIa4bgo.com
    by samuel(匿名) on 2010/2/4 15:37:58
  • Koxtggnh
    It's serious &lt;a href=&quot; http://www.newsland.it/nr/article/it-alt.faq/3298.html &q...
    by Koxtggnh(匿名) on 2010/2/4 6:09:20
  • SrehssllMZjp
    XefKdm &lt;a href=&quot;http://onztwqzldpty.com/&quot;&gt;onztwqzldpty&lt;/a&am...
    by fsfirjqclpn(匿名) on 2010/2/4 0:43:23
  • OLDLqAKsuD
    BnPVvu &lt;a href=&quot;http://jzyknfzplvon.com/&quot;&gt;jzyknfzplvon&lt;/a&am...
    by ofudghioo(匿名) on 2010/2/4 0:07:18
  • Hwbjmqub
    Punk not dead &lt;a href=&quot; http://www.newsland.it/nr/article/it-alt.faq/3238.html &...
    by Hwbjmqub(匿名) on 2010/2/3 14:14:20
  • Re
    From time to time different students have assignments to compose the &lt;a href=&quot;http:/...
    by Rebeccamp28(匿名) on 2010/2/3 11:04:43
  • emRTIwMZOMDFfCg
    nQf5M6 &lt;a href=&quot;http://eaykuvqnrful.com/&quot;&gt;eaykuvqnrful&lt;/a&am...
    by pnxjuwq(匿名) on 2010/2/2 23:36:36
  • jPRCuLgHySwb
    qc0qb5 &lt;a href=&quot;http://ciktzfijfsfj.com/&quot;&gt;ciktzfijfsfj&lt;/a&am...
    by yuplvewx(匿名) on 2010/2/2 19:05:07
  • re:IP to Integer
    IPV6呢?
    by howie(匿名) on 2010/2/2 10:34:10
  • IcqpxCPAVoKn
    Ff4AZo &lt;a href=&quot;http://bovwngagtlua.com/&quot;&gt;bovwngagtlua&lt;/a&am...
    by mbnbusiuh(匿名) on 2010/2/1 18:40:41
  • tJZDsNznVk
    scXyAq &lt;a href=&quot;http://pqtnkiwdacoa.com/&quot;&gt;pqtnkiwdacoa&lt;/a&am...
    by lwummgsncve(匿名) on 2010/2/1 3:53:51
  • Okurlpzt
    i'm fine good work &lt;a href=&quot; http://littlelolitasmodels.vox.com/ &quot;&gt;p...
    by Okurlpzt(匿名) on 2010/1/31 19:30:08
  • Sgoonhvn
    Excellent work, Nice Design &lt;a href=&quot; http://littlelolitasmodels.vox.com/ &quot;...
    by Sgoonhvn(匿名) on 2010/1/31 18:29:47
  • Zloozuuj
    Punk not dead &lt;a href=&quot; http://lolitatoplist.vox.com/ &quot;&gt;lolita mpeg...
    by Zloozuuj(匿名) on 2010/1/31 17:52:04
  • Jmqskdlf
    I love this site &lt;a href=&quot; http://younglolitasbbs.vox.com/ &quot;&gt;preetee...
    by Jmqskdlf(匿名) on 2010/1/31 15:09:12
  • Tmmhaxbr
    Wonderfull great site &lt;a href=&quot; http://lolitabbs969.vox.com &quot;&gt;lolita...
    by Tmmhaxbr(匿名) on 2010/1/31 14:31:36
  • Asnejtjx
    real beauty page &lt;a href=&quot; http://underagelolitas.vox.com/ &quot;&gt;top 50 ...
    by Asnejtjx(匿名) on 2010/1/31 12:51:18
  • Tibtihsu
    &lt;a href=&quot; http://lolitamodels.vox.com/ &quot;&gt;real young lolitas&lt;...
    by Tibtihsu(匿名) on 2010/1/31 7:50:15
  • Jlcdzoem
    Very Good Site &lt;a href=&quot; http://lolitamodels.vox.com/ &quot;&gt;kds pedo lol...
    by Jlcdzoem(匿名) on 2010/1/31 6:47:06
  • Eqczveev
    i'm fine good work &lt;a href=&quot; http://mipagina.univision.com/preteenlolitabbs/ &qu...
    by Eqczveev(匿名) on 2010/1/31 6:08:16
  • Ndhvewjd
    Very interesting tale &lt;a href=&quot; http://mipagina.univision.com/preteenlolitabbs/ &...
    by Ndhvewjd(匿名) on 2010/1/31 5:06:34
  • Jktojpnv
    &lt;a href=&quot; http://mipagina.univision.com/preteenlolitamodels/ &quot;&gt;goth...
    by Jktojpnv(匿名) on 2010/1/31 3:27:26
  • Lftiemmn
    Very interesting tale &lt;a href=&quot; http://mipagina.univision.com/preteenyounglolitas/ &...
    by Lftiemmn(匿名) on 2010/1/31 2:51:02
  • ITYAtUVjqijsAcZ
    4SnRK4 &lt;a href=&quot;http://lbmuqlnscvjk.com/&quot;&gt;lbmuqlnscvjk&lt;/a&am...
    by pqoqxfvrbcb(匿名) on 2010/1/30 19:25:06
  • bjhbHxudMahxGCkiue
    3mRPzg &lt;a href=&quot;http://rzitclgaemis.com/&quot;&gt;rzitclgaemis&lt;/a&am...
    by quglkot(匿名) on 2010/1/30 19:20:51

广告

【第1页/共19页,655条】
首页
前页
1
...
2010年02月07日

图均来自网络,如下,这几幅图对理解控件的继承关系很有帮助:

image_3

DispatcherObject: WPF/Silverlight 中有许多类继承自DispatcherObject,DispatcherObject提供了处理同步和并发的基本构造。

DependencyObject :构建WPF/Silverlight的一个主要思想是属性优先于方法和事件。WPF/Silverlight 提供了丰富的属性系统,其核心是DependencyObject。

Visual:该类的主要作用是为WPF/Silverlight 提供2D呈现支持,主要包括输出显示,坐标转换,区域剪切等。

UIElement:该类继承自Visual类,是构建WPF/Silverlight元素和基本呈现特征的基类,其中定义很多与输入和焦点有关的特性,例如键盘事件,鼠标,还包括一些与WPF事件模型有关的API。

FrameworkElement:继承了UIElement类,而且还添加了一些功能,例如,布局定义、逻辑树、对象生命周期事件、支持数据绑定和动态资源引用、支持样式和动画。

image3

Control是创建自定义应用程序控件的基类。可以重写Control类所提供的属性,方法,事件等,为自定义控件添加自定义逻辑。 构建WPF/Silvlerlight  应用程序页面的window类就派生自它.还有button,TextBox等控件也派生自他。

Shape:WPF/Silvlerlight 中呈现二维矢量图形的基础类。有 Line、Polyline、Polygon、Path、Rectangle 和 Ellipse等子类。可从 Shape 类进行派生以实现自定义矢量图形基元。从 Shape 派生是确保这些自定义基元使用 WPF/Silvlerlight 布局系统的协议的最简单方法。

posted on 2010-02-07 18:01:30 by ghj1976  评论(1) 阅读(748)

 

和传统属性的区别在哪里,为什么要搞出这样一个DependencyProperty呢?

  • 内存使用量。
    我们设计控件,不可避免的要设计很多控件的属性,高度,宽度等等,这样就会有大量(私有)字段的存在,一个继承树下来,低端的对象会无法避免的膨胀。而外部通过GetValue,SetValue暴露属性,内部维护这样一个EffectiveValueEntry的数组,顾名思义,只是维护了一个有效的、设置过值的列表,可以减少内存的使用量。
  • 传统属性的局限性。
    这个有很多,包括一个属性只能设置一个值,不能得到变化的通知,无法为现有的类添加新的属性等等。

在 MSDN 中,提到当你有下面四种情况时,应该考虑使用DependencyProperty:

  • 您希望可在样式中设置此属性。
  • 您希望此属性支持数据绑定。
  • 您希望此属性支持经过动画处理的值。
  • 您希望 Silverlight 属性系统在属性系统本身、环境或用户执行的操作或者读取并使用样式而更改了属性以前的值时进行报告。您的属性可以指定在每次属性系统确定属性值已被明确更改时将调用的回调方法。

 

一个Silverlight中创建 DependencyProperty 的例子

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;

namespace SilverlightApplication2
{
    public partial class SilverlightControl1 : UserControl
    { 

        /// <summary>
        /// Declare the dependency property as static, readonly field in your class.    
        /// </summary>
        public static readonly DependencyProperty AquariumGraphicProperty 
            = DependencyProperty.Register(
          "AquariumGraphic",                                        // Property name
          typeof(Uri),                                              // Property type
          typeof(SilverlightControl1),                              // Type of the dependency property provider
          new PropertyMetadata(null,                                // 默认的值
              new PropertyChangedCallback(OnUriChanged)               // Callback invoked on property value has changes
          )
        );

        /// <summary>
        /// Create the property and use the SetValue/GetValue methods of the DependencyObject class
        /// </summary>
        public Uri AquariumGraphic
        {
            get { return (Uri)GetValue(AquariumGraphicProperty); }
            set { SetValue(AquariumGraphicProperty, value); }
        }
             
        public SilverlightControl1()
        {
            InitializeComponent();
        }        
     
        /// <summary>
        /// 值变化时,更新显示
         /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnUriChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Shape sh = (Shape)d;
            ImageBrush ib = new ImageBrush();
            ib.ImageSource = new BitmapImage(e.NewValue as Uri);
            sh.Fill = ib;
        }

     
    }
}

我们首先来看看 AquariumGraphicProperty ,类型就是DependencyProperty,前面用了static readonly,一个单例模式,有DependencyProperty.Register,看起来像是往容器里注册,其实也差不多。

再来看AquariumGraphic,和传统的属性没什么区别,类型是 Uri 型,有get,set方法。只不过内部的实现分别调用了GetValue和SetValue,这两个方法是DependecyObject(简称DO,是WPF/Silverlight中所有可视Visual的基类)暴露出来的,传入的参数是AquariumGraphicProperty。

需要注意的是运行时,Xaml中是直接调用GetValue和SetValue的。所以,为了让使用XAML设置属性与使用代码设置属性一致,在属性包装器中除了GetValue和SetValue调用以外,不应该包含任何其他逻辑,这是非常重要的。如果需要添加自定义逻辑,应该在Register的回调函数中添加。

 

参考资料:

.Net3.0里的DependencyProperty(1):引入了DP的一些基本概念
http://www.cnblogs.com/yayx/archive/2007/05/26/761117.html

WPF里的DependencyProperty(2):DP的应用,主要想解释我们为什么要用它
http://www.cnblogs.com/yayx/archive/2008/04/20/1162963.html

WPF里的DependencyProperty(3):主要想演示下怎么用DP
http://www.cnblogs.com/yayx/archive/2008/04/22/1166064.html

WPF/Silverlight为什么要使用Canvas.SetLeft()这样的方法? :附属,从布局应用上解释了下为什么要有AttachedProperty
http://www.cnblogs.com/yayx/archive/2008/04/23/1167110.html

WPF里的DependencyProperty(4):介绍了DP的工作机制
http://www.cnblogs.com/yayx/archive/2008/04/24/1168738.html

WPF里的DependencyProperty(5) :介绍了PropertyMetadata和AttachedProperty
http://www.cnblogs.com/yayx/archive/2008/06/03/1213126.html

Windows Presentation Foundation 体系结构
http://msdn.microsoft.com/en-us/ms750441(zh-cn).aspx

如何学好WPF
http://www.cnblogs.com/zhouyongh/archive/2009/07/31/1536000.html

Tip: How to declare a dependency property in Silverlight?
http://www.silverlightshow.net/tips/Tip-How-to-declare-a-dependancy-property-in-Silverlight.aspx

WPF体系结构-- System.Windows.DependencyObject与智能的控件
http://bbniu.com/forum/thread-478-1-1.html

图解DotNet框架之九:WPF
http://www.cnblogs.com/xugao918/archive/2008/08/01/1258193.html

Silverlight自定义依赖项对象和依赖项属性
http://msdn.microsoft.com/zh-cn/library/cc903933(VS.95).aspx

posted on 2010-02-07 16:35:41 by ghj1976  评论(0) 阅读(797)

 
2010年02月02日

前一篇博客 IP to Integer 提供的 SQL 函数是 IP 转换成 Integer 的方法。 Integer 的最大值为: 2147483647(2^31 - 1)。按照 IP 转换成整数的算法,会算出来大于这个值的,所以之前提供的 IP 转换成 Integer 的方法会算出负值。

下面是 IP to BigInt 的转换算法, 这时候运算就不会小于零。

CREATE FUNCTION dbo.ipStringToBigInt 
( 
    @ip CHAR(15) 
) 
RETURNS bigint 
AS 
BEGIN 
    DECLARE @rv bigint, 
        @o1 bigint, 
        @o2 INT, 
        @o3 INT, 
        @o4 INT
 
    SELECT 
        @o1 = CONVERT(INT, PARSENAME(@ip, 4)), 
        @o2 = CONVERT(INT, PARSENAME(@ip, 3)), 
        @o3 = CONVERT(INT, PARSENAME(@ip, 2)), 
        @o4 = CONVERT(INT, PARSENAME(@ip, 1)) 
 
    IF (@o1 BETWEEN 0 AND 255) 
        AND (@o2 BETWEEN 0 AND 255) 
        AND (@o3 BETWEEN 0 AND 255) 
        AND (@o4 BETWEEN 0 AND 255) 
    BEGIN      
 
        SET @rv = (@o1 * 16777216)  +  
            (@o2 * 65536) +  
            (@o3 * 256) + 
            (@o4) 
    END 
    ELSE 
        SET @rv = -1 
    RETURN @rv 
END
go 



CREATE FUNCTION dbo.ipBigIntToString 
( 
    @ip bigint 
) 
RETURNS CHAR(15) 
AS 
BEGIN 
    DECLARE @o1 INT, 
        @o2 INT, 
        @o3 INT, 
        @o4 INT 
 
    IF @ip > 4294967295 RETURN '255.255.255.255' 
    IF @ip <= 0 RETURN '0.0.0.0' 
 
    SET @o1 = @ip / 16777216
 
    SET @ip = @ip % 16777216 
    SET @o2 = @ip / 65536 
    SET @ip = @ip % 65536 
    SET @o3 = @ip / 256 
    SET @ip = @ip % 256 
    SET @o4 = @ip 
 
    RETURN 
        CONVERT(VARCHAR(4), @o1) + '.' + 
        CONVERT(VARCHAR(4), @o2) + '.' + 
        CONVERT(VARCHAR(4), @o3) + '.' + 
        CONVERT(VARCHAR(4), @o4) 
END

go 

-- 调用例子
select dbo.ipBigIntToString(3708279131)
select dbo.ipStringToBigInt('221.7.217.91')

posted on 2010-02-02 11:22:53 by ghj1976  评论(0) 阅读(1312)

 
2010年02月01日

MatrixTransform 通过创建一个任意仿射矩阵变换,用于操作二维平面中的对象或坐标系。由于仿射变换时,平行的边依然平行,所以,我们无法对一个矩形的位图进行随意变换,比如我们无法拉伸一个角,也无法进行把它变成梯形等。如下图所示:就类似光线照射下,图形的投影。

01000000000000119081530541941

如下图,从矩形是无法转换成后一种的。

t_affine

旋转、倾斜、平移、缩放 是最常用的仿射变换,对应就是RotateTransform、SkewTransform、TranslateTransform、ScaleTransform 类。

有关这四种变化可以参看我之前写的博客:

Silverlight学习笔记--通用绘图属性
http://blog.joycode.com/ghj/archive/2009/11/30/115793.joy

Silverlight 图形的转换
http://blog.joycode.com/ghj/archive/2010/01/05/115841.joy

由于 MatrixTransform之相关矩阵运算 可以看下面我写的博客:
http://blog.joycode.com/ghj/archive/2010/01/28/115865.joy 

 

MatrixTransform主要通过点的矩阵变换来实现图形的改变,我们常看到的一些效果,如对称效果,就可以通过矩阵变换来实现。

首先,我们先来了解一下MatrixTransform的所有参数的意义,MatrixTransform的参数如下:{M11, M 12, M 21, M22, OffesetX,OffsetY}

其中:{ M11, M12, M21, M22}构成一个矩阵A,用于坐标的变换,{ OffesetX,OffsetY }构成平移向量O,用于坐标的平移。

 

据我在Google上搜索,使用 MatrixTransform 并没有提供更多的 仿射变换 功能,我们使用 MatrixTransform 来创建 自定义变换也就是旋转、倾斜、平移、缩放这几种的组合。

 

下面是一个演示,我们可以手工修改 M11, M 12, M 21, M22, OffesetX,OffsetY ,继而可以看到矩形的变化效果,在输入框上滚动鼠标中轮也可以增加或者减少数字。

 

演示程序的代码:

Xaml 文件

<UserControl x:Class="SilverlightApp_MatrixTransform.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="200" d:DesignWidth="400" >

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="50"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.33*"/>
            <RowDefinition Height="0.34*"/>
            <RowDefinition Height="0.33*"/>
        </Grid.RowDefinitions>
        <Rectangle Fill="#FF186ED0" Stroke="Black" Grid.Column="0" Grid.Row="0" Grid.RowSpan="3" x:Name="rectangle" 
                   Width="100" Height="100" VerticalAlignment="Center" HorizontalAlignment="Center">
            <Rectangle.RenderTransform>
                <MatrixTransform x:Name="rectangleMatrix">
                </MatrixTransform>
            </Rectangle.RenderTransform>
        </Rectangle>
        <TextBlock Grid.Column="1" Grid.Row="0"  Text="M11:" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        <TextBox x:Name="tb_M11"  Text="1.0" VerticalAlignment="Center" TextAlignment="Center" 
                 Grid.Row="0" Grid.Column="2" d:LayoutOverrides="Width" />
        <TextBlock Grid.Column="3" Grid.Row="0"  Text="M12:" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        <TextBox x:Name="tb_M12"  Text="0.0" VerticalAlignment="Center" TextAlignment="Center"
                 Grid.Row="0" Grid.Column="4" d:LayoutOverrides="Width" />

        <TextBlock Grid.Column="1" Grid.Row="1"  Text="M21:" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        <TextBox x:Name="tb_M21"  Text="0.0" VerticalAlignment="Center" TextAlignment="Center" 
                 Grid.Row="1" Grid.Column="2" d:LayoutOverrides="Width" />
        <TextBlock Grid.Column="3" Grid.Row="1"  Text="M22:" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        <TextBox x:Name="tb_M22"  Text="1.0" VerticalAlignment="Center" TextAlignment="Center" 
                 Grid.Row="1" Grid.Column="4" d:LayoutOverrides="Width" />

        <TextBlock Grid.Column="1" Grid.Row="2"  Text="offsetX:" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        <TextBox x:Name="tb_offsetX"  Text="0.0" VerticalAlignment="Center" TextAlignment="Center" 
                 Grid.Row="2" Grid.Column="2" d:LayoutOverrides="Width" />
        <TextBlock Grid.Column="3" Grid.Row="2"  Text="offsetY:" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        <TextBox x:Name="tb_offsetY"  Text="0.0" VerticalAlignment="Center" TextAlignment="Center" 
                 Grid.Row="2" Grid.Column="4" d:LayoutOverrides="Width" />

    </Grid>
</UserControl>

C# 文件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightApp_MatrixTransform
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        Matrix m = new Matrix();

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            this.tb_M11.MouseWheel += new MouseWheelEventHandler(TextBox_MouseWheel);
            this.tb_M11.GotFocus += new RoutedEventHandler(TextBox_GotFocus);
            this.tb_M11.TextChanged += new TextChangedEventHandler(TextBox_TextChanged);
            this.tb_M12.MouseWheel += new MouseWheelEventHandler(TextBox_MouseWheel);
            this.tb_M12.GotFocus += new RoutedEventHandler(TextBox_GotFocus);
            this.tb_M12.TextChanged += new TextChangedEventHandler(TextBox_TextChanged);
            this.tb_M21.MouseWheel += new MouseWheelEventHandler(TextBox_MouseWheel);
            this.tb_M21.GotFocus += new RoutedEventHandler(TextBox_GotFocus);
            this.tb_M21.TextChanged += new TextChangedEventHandler(TextBox_TextChanged);
            this.tb_M22.MouseWheel += new MouseWheelEventHandler(TextBox_MouseWheel);
            this.tb_M22.GotFocus += new RoutedEventHandler(TextBox_GotFocus);
            this.tb_M22.TextChanged += new TextChangedEventHandler(TextBox_TextChanged);
            this.tb_offsetX.MouseWheel += new MouseWheelEventHandler(TextBox_MouseWheel);
            this.tb_offsetX.GotFocus += new RoutedEventHandler(TextBox_GotFocus);
            this.tb_offsetX.TextChanged += new TextChangedEventHandler(TextBox_TextChanged);
            this.tb_offsetY.MouseWheel += new MouseWheelEventHandler(TextBox_MouseWheel);
            this.tb_offsetY.GotFocus += new RoutedEventHandler(TextBox_GotFocus);
            this.tb_offsetY.TextChanged += new TextChangedEventHandler(TextBox_TextChanged);
        }

        private void TextBox_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            TextBox tb = sender as TextBox;
            if (tb == null) return;
            double w = 1.0;
            if (double.TryParse(tb.Text, out w))
                w = w + (double)e.Delta / 100;
            else
                w = 1.0;
            if (tb != null)
                tb.Text = w.ToString();
        }

        private void TextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            TextBox box = sender as TextBox;
            box.Select(0, box.Text.Length);
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox tb = sender as TextBox;
            if (tb == null) return;

            double w = 1.0;
            if (!double.TryParse(tb.Text, out w)) w = 1.0;

            switch (tb.Name)
            {
                case "tb_M11":
                    m.M11 = w;
                    break;
                case "tb_M12":
                    m.M12 = w;
                    break;
                case "tb_M21":
                    m.M21 = w;
                    break;
                case "tb_M22":
                    m.M22 = w;
                    break;
                case "tb_offsetX":
                    m.OffsetX = w;
                    break;
                case "tb_offsetY":
                    m.OffsetY = w;
                    break;
                default:
                    break;
            }
            rectangleMatrix.Matrix = m;
        }
    }
}

参考资料:

WPF中的MatrixTransform
http://www.cnblogs.com/zhouyinhui/archive/2007/07/07/809553.html

稳扎稳打Silverlight(10) - 2.0其它之Transform详解,以及UIElement和FrameworkElement的常用属性
http://www.cnblogs.com/webabcd/archive/2008/11/03/1325150.html

MatrixTransform 类
http://msdn.microsoft.com/zh-cn/library/system.windows.media.matrixtransform.aspx

Basic Understanding of Matrix Transformation
http://blogs.msdn.com/joseph_fultz/archive/2009/07/31/basic-understanding-of-matrix-transformation.aspx

Silverlight Terrain Tutorial Part 2 – Using Transform Matrices to Create 3D Looking Terrain.
http://blogs.silverlight.net/blogs/msnow/archive/2008/08/18/terrain-tutorial-part-2-using-transform-matrices-to-create-3d-looking-terrain.aspx

MatrixTransform
http://blogs.msdn.com/jstegman/archive/2006/04/02/566939.aspx

WPF中MatrixTransform的理解与应用
http://blog.csdn.net/artlife/archive/2007/01/08/1477360.aspx

二维几何图形变换及其GDI+实现
http://www.cnblogs.com/begincsdn/archive/2005/07/14/193005.html

Silverlight Transforms
http://msdn.microsoft.com/en-us/library/cc189037(VS.95).aspx

Understanding the Transformation Matrix in Flash 8
http://www.senocular.com/flash/tutorials/transformmatrix/

Transformation Matrix in Silverlight 2
http://joel.neubeck.net/2008/09/transformation-matrix-in-silverlight-2/

AS3位图任意形变一步一步来(2)——计算变换矩阵
http://fdream.net/blog/article/632.aspx

posted on 2010-02-01 14:56:44 by ghj1976  评论(0) 阅读(1296)

 
2010年01月28日

有时候我们要判断某个IP是否在某个段内,如何实现呢? 一个简单办法就是把IP转换成Integer,然后判断整数是否在某个范围内就可以实现这个判断。

转换的算法如下:

比如我们要转换的IP为: 058.062.042.000

First Octet: 058
Second Octet: 062
Third Octet: 042
Fourth Octet: 000

计算公式如下:
(first octet * 256³) + (second octet * 256²) + (third octet * 256) + (fourth octet)
=  (first octet * 16777216) + (second octet * 65536) + (third octet * 256) + (fourth octet)
=  (058 * 16777216) + (062 * 65536) + (042 * 256) + (000)
=  977152512

网上有现成的服务,比如下面这个地址:

http://www.aboutmyip.com/AboutMyXApp/IP2Integer.jsp

SQL Server 的一个例子如下:

CREATE FUNCTION dbo.ipStringToInt 
( 
    @ip CHAR(15) 
) 
RETURNS INT 
AS 
BEGIN 
    DECLARE @rv INT, 
        @o1 INT, 
        @o2 INT, 
        @o3 INT, 
        @o4 INT, 
        @base INT 
 
    SELECT 
        @o1 = CONVERT(INT, PARSENAME(@ip, 4)), 
        @o2 = CONVERT(INT, PARSENAME(@ip, 3)), 
        @o3 = CONVERT(INT, PARSENAME(@ip, 2)), 
        @o4 = CONVERT(INT, PARSENAME(@ip, 1)) 
 
    IF (@o1 BETWEEN 0 AND 255) 
        AND (@o2 BETWEEN 0 AND 255) 
        AND (@o3 BETWEEN 0 AND 255) 
        AND (@o4 BETWEEN 0 AND 255) 
    BEGIN      
        SELECT @base = CASE 
            WHEN @o1 < 128 THEN 
                (@o1 * 16777216) 
            ELSE 
                -(256 - @o1) * 16777216 
            END 
     
        SET @rv = @base +  
            (@o2 * 65536) +  
            (@o3 * 256) + 
            (@o4) 
    END 
    ELSE 
        SET @rv = -1 
    RETURN @rv 
END
go

调用范例:

select dbo.ipStringToInt('058.062.042.000')

整数转换如下:

CREATE FUNCTION dbo.ipIntToString 
( 
    @ip INT 
) 
RETURNS CHAR(15) 
AS 
BEGIN 
    DECLARE @o1 INT, 
        @o2 INT, 
        @o3 INT, 
        @o4 INT 
 
    IF ABS(@ip) > 2147483647 
        RETURN '255.255.255.255' 
 
    SET @o1 = @ip / 16777216 
 
    IF @o1 = 0 
        SELECT @o1 = 255, @ip = @ip + 16777216 
 
    ELSE IF @o1 < 0 
    BEGIN 
        IF @ip % 16777216 = 0 
            SET @o1 = @o1 + 256 
        ELSE 
        BEGIN 
            SET @o1 = @o1 + 255 
            IF @o1 = 128 
                SET @ip = @ip + 2147483648 
            ELSE 
                SET @ip = @ip + (16777216 * (256 - @o1)) 
        END 
    END 
    ELSE 
    BEGIN 
        SET @ip = @ip - (16777216 * @o1) 
    END 
 
    SET @ip = @ip % 16777216 
    SET @o2 = @ip / 65536 
    SET @ip = @ip % 65536 
    SET @o3 = @ip / 256 
    SET @ip = @ip % 256 
    SET @o4 = @ip 
 
    RETURN 
        CONVERT(VARCHAR(4), @o1) + '.' + 
        CONVERT(VARCHAR(4), @o2) + '.' + 
        CONVERT(VARCHAR(4), @o3) + '.' + 
        CONVERT(VARCHAR(4), @o4) 
END
go

调用范例:

select dbo.ipIntToString(977152512)

C# 的例子如下:

using System;
using System.Net;

namespace ConsoleApplication1
{
    class Program
    {
        static long ToInt(string addr)
        {
            return BitConverter.ToInt32(IPAddress.Parse(addr).GetAddressBytes(), 0); 
        }

        static string ToAddr(long address)
        {
            return IPAddress.Parse(address.ToString()).ToString();
            // This also works: 
            // return new IPAddress((uint) IPAddress.HostToNetworkOrder( 
            //    (int) address)).ToString(); 
        }

        static void Main(string[] args)
        {
            Console.WriteLine(ToInt("64.233.187.99"));
            Console.WriteLine(ToAddr(1089059683)); 

            Console.ReadLine();
        }
    }
}

参考资料:

How should I store an IP address in SQL Server?
http://sqlserver2000.databases.aspfaq.com/how-should-i-store-an-ip-address-in-sql-server.html

How to convert an IPv4 address into a integer in C#?
http://stackoverflow.com/questions/461742/how-to-convert-an-ipv4-address-into-a-integer-in-c

posted on 2010-01-28 15:04:44 by ghj1976  评论(3) 阅读(1871)

 

最近在学习MatrixTransform,发现对之前学的矩阵乘法竟然忘的一干二净,下面就是这个基础知识的整理。

 

矩阵加法

通常的矩阵加法被定义在两个相同大小的矩阵。两个m×n矩阵A和B的和,标记为A+B,一样是个m×n矩阵,其内的各元素为其相对应元素相加后的值。例如:

973b1461ec9b7c49a781e39aa22623c2

也可以做矩阵的减法,只要其大小相同的话。A-B内的各元素为其相对应元素相减后的值,且此矩阵会和A、B有相同大小。例如:

8e411287f504ba4fe4b6a9a93d2a4f03

 

矩阵乘法

若给出一矩阵 A 及一数字 c,可定义标量积 cA,其中 (cA)[i, j] = cA[i, j]。 例如:

8951d4762a38dcb7a372bb6a5ee0d623

 

设A和B是两个给定如下的矩阵:

95d86d25f324076227a08a1de8ffebbb  b692829bf4f96dbcadb20d1de06aa8a6

8dd1d643ed85e951c415a39cf690b659

举例来说: 

7b62cda9a2e78e8414806c5aea486b5c d3c223ed4af4939e565893b2f3136bae

MatrixTransform  的矩阵运算

假设我们有个点(X,Y) ,我们使用 MatrixTransform  要把它转换成新的点(X1,Y1),则公式为:

X1 = X*M11 + Y*M21+ OffsetX
Y1 = X*M12 + Y*M22+ OffsetY

在Silverlight 和 WPF 中,对应的Xaml 如下:

<MatrixTransform Matrix="M11, M12, M21, M22, OffsetX, OffsetY"/> 

从矩阵运算的角度,就是如下矩阵运算:

image

上述表达式中,乘号左面矩阵的列为为系数表,右边矩阵为向量表。例如,第一行是[X Y 1],因此将X乘上第一个向量,Y乘上第二个向量,1则乘上第三个向量。

参考资料:

矩阵
http://zh.wikipedia.org/zh-cn/%E7%9F%A9%E9%98%B5

矩阵加法
http://zh.wikipedia.org/zh-cn/%E7%9F%A9%E9%99%A3%E5%8A%A0%E6%B3%95

矩阵乘法
http://zh.wikipedia.org/zh-cn/%E7%9F%A9%E9%99%A3%E4%B9%98%E6%B3%95

3D 图形编程的数学基础(2) 矩阵及其运算
http://blog.csdn.net/vagrxie/archive/2009/12/09/4974985.aspx

WPF中的MatrixTransform
http://www.cnblogs.com/zhouyinhui/archive/2007/07/07/809553.html

MatrixTransform
http://blogs.msdn.com/jstegman/archive/2006/04/02/566939.aspx

SVG 的矢量运算
http://www.w3.org/TR/SVG11/coords.html#TransformMatrixDefined

posted on 2010-01-28 10:00:08 by ghj1976  评论(0) 阅读(1617)

 
2010年01月25日

我们使用Blend 设计WPF或者Silverlight 界面是,会看到有两个选择工具,下面就是他们的对比。

  选择工具 路径选择工具
截图 image image
英文名称 Selection Direct Selection
作用 在美工板上选择要修改的形状、路径和对象。跟普通的选择鼠标一样 显示在绘制路径上的节点,并对各个节点进行操作。
  如下图所示,选择这个元素的整体 对非Path对象来说,就是选择整体,对Path对象来说如下,可以选择Path的每一个关键点,并对他们进行设置。
对路径的处理 image image
鼠标操作 如上图所示,移动对象的位置。 当鼠标在Path上移动时,可能是下面五种鼠标,对应的是五种功能。
image
移动点指针,用于 使路径上的点显示切线图柄 方法就是: 单击路径上的点 或者 用于 移动路径上的点 方法就是: 拖动路径上的点;
image 移动段指针,用于 使路径上两点之间的段显示切线图柄 方法就是 单击路径段 或者 用于 移动路径上两点之间的段 方法就是 拖动路径段;
image 移动切线指针,用于 更改路径上的点的切线角度 方法就是 单击路径上的点或线段以显示切线图柄,然后拖动其中一个切线端点
image 转换点指针,用于 使点成为锐角,或者将切线的长度缩短为零 或者 使任何锐角变得平滑(或者,如果已经平滑,则通过单击点来更改曲线的角度); 方法就是: 悬停在某个点上,按住 Alt,然后拖动此点
image 转换段指针,用于 将曲线段改为直线段 或者 获取一条段,并使其弯曲通过指针位置, 方法就是 : 悬停在路径中的某条线段上,按住 Alt,然后拖动线段;
也可以 独立于另一边调整切线的一端 ,方法就是: 直接选择一个点或一条线段,按住 Alt,然后拖动一个切线端点。

注:若要添加或删除现有路径上的点,或者连接两个现有路径,请使用"笔"工具。

上面我们可以看到 , 路径选择工具 跟笔工具息息相关。下面是笔工具的一些用法。

 

image 笔指针

创建直线段的起点,方法: 单击以创建新点;

创建曲线段的起点,方法: 单击以创建新点,然后拖动以调整切线图柄,最后再松开鼠标按钮;

 

image  笔调整指针

调整最后一条切线时不应用平滑约束,因此可以生成锐角,方法: 单击以创建新点,然后按 Alt,最后再松开鼠标按钮;

分割最后一条切线,使切线的端点保持独立,因此可以生成锐角,方法: 单击以创建新点,然后按下 Alt 并拖动,最后再松开鼠标按钮;

按 15 度的增量在新点周围移动切线端点,方法: 单击以创建新点,然后按下 Shift+Alt 并拖动,最后再松开鼠标按钮;

在一个端点处将切线长度减小为零, 方法: 单击该端点;

 

 image 笔插入指针

向现有路径添加新点,方法: 单击路径中需要新点的位置;

 

image  笔删除指针

从路径中删除点,方法: 悬停在现有点上并单击;

 

image 笔封闭指针

用锐角封闭路径,方法: 单击该起点;

在角部用平滑曲线封闭路径,方法: 单击起点并拖动以修改切线图柄,然后松开鼠标按钮;

 

image  笔连接指针

连接两条路径时创建锐角,方法: 选择两条路径,依次单击"笔"工具、一条路径的端点以及另一条路径的端点;

连接两条路径时创建平滑角点,方法: 选择两条路径,依次单击"笔"工具和一条路径的端点,然后拖动另一条路径的端点;

 

image  笔开始指针

新建路径,方法: 按下 Ctrl 并在前一条路径的外部单击,以停止向前一条路径中添加点,然后在所需的新路径开始位置单击或拖动;

posted on 2010-01-25 14:45:23 by ghj1976  评论(0) 阅读(1710)

 
2010年01月22日

在Silverlight中,贝塞尔曲线在很多地方都使用到了,下面是就贝塞尔曲线的一些基础知识:

贝塞尔曲线又称贝兹曲线或贝济埃曲线,一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。如下图:

0b14ad1956fc9d5643a9ade9

贝塞尔曲线是应用于二维图形应用程序的数学曲线。曲线的定义有四个点:起始点、终止点(也称锚点)以及两个相互分离的中间点。滑动两个中间点,贝塞尔曲线的形状会发生变化。二十世纪六十年代晚期,Pierre Bézier应用数学方法为雷诺公司的汽车制造业描绘出了贝塞尔曲线。

贝塞尔曲线就是这样的一条曲线,它是依据四个位置任意的点坐标绘制出的一条光滑曲线。在历史上,研究贝塞尔曲线的人最初是按照已知曲线参数方程来确定四个点的思路设计出这种矢量曲线绘制法。贝塞尔曲线的有趣之处更在于它的“皮筋效应”~也就是说,随着点有规律地移动,曲线将产生皮筋伸引一样的变换,带来视觉上的冲击。1962年,法国数学家Pierre Bézier第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名~是为贝塞尔曲线。

 

建构贝塞尔曲线

1、线性曲线


线性贝塞尔曲线演示动画,t in [0,1]
线性贝塞尔曲线函数中的 t 会经过由 P0 至 P1 的 B(t) 所描述的曲线。例如当 t=0.25 时,B(t) 即一条由点 P0 至 P1 路径的四分之一处。就像由 0 至 1 的连续 t,B(t) 描述一条由 P0 至 P1 的直线。如下图所示:

 

Bezier_1_big
线性贝塞尔曲线演示动画,t in [0,1]

 

2、二次曲线


为建构二次贝塞尔曲线,可以中介点 Q0 和 Q1 作为由 0 至 1 的 t:

由 P0 至 P1 的连续点 Q0,描述一条线性贝塞尔曲线。
由 P1 至 P2 的连续点 Q1,描述一条线性贝塞尔曲线。
由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。

 Bezier_2_big 

二次贝塞尔曲线的结构

Bezier_2_big

二次贝塞尔曲线演示动画,t in [0,1]

3、三阶曲线

为建构高阶曲线,便需要相应更多的中介点。对于三次曲线,可由线性贝塞尔曲线描述的中介点 Q0、Q1、Q2,和由二次曲线描述的点 R0、R1 所建构:

Bezier_3_big 

三次贝塞尔曲线的结构

Bezier_3_big

三次贝塞尔曲线演示动画,t in [0,1]

4、四次曲线

对于四次曲线,可由线性贝塞尔曲线描述的中介点 Q0、Q1、Q2、Q3,由二次贝塞尔曲线描述的点 R0、R1、R2,和由三次贝塞尔曲线描述的点 S0、S1 所建构:

Bezier_4_big 

四次贝塞尔曲线的结构

Bezier_4_big

 

四次贝塞尔曲线演示动画,t in [0,1]

5、五阶贝塞尔曲线

 

BezierCurve

五阶贝塞尔曲线的构成。

 

代码演示:

C++ 产生三次方贝塞尔曲线的代码

/*
 產生三次方貝茲曲線的程式碼
*/
 
typedef struct
{
    float x;
    float y;
}
Point2D;
 
/*
 cp 在此是四個元素的陣列:
 cp[0] 為起始點,或上圖中的 P0
 cp[1] 為第一個控制點,或上圖中的 P1
 cp[2] 為第二個控制點,或上圖中的 P2
 cp[3] 為結束點,或上圖中的 P3
 t 為參數值,0 <= t <= 1
*/
 
Point2D PointOnCubicBezier( Point2D* cp, float t )
{
    float   ax, bx, cx;
    float   ay, by, cy;
    float   tSquared, tCubed;
    Point2D result;
 
    /* 計算多項式係數 */
 
    cx = 3.0 * (cp[1].x - cp[0].x);
    bx = 3.0 * (cp[2].x - cp[1].x) - cx;
    ax = cp[3].x - cp[0].x - cx - bx;
 
    cy = 3.0 * (cp[1].y - cp[0].y);
    by = 3.0 * (cp[2].y - cp[1].y) - cy;
    ay = cp[3].y - cp[0].y - cy - by;
 
    /* 計算位於參數值 t 的曲線點 */
 
    tSquared = t * t;
    tCubed = tSquared * t;
 
    result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x;
    result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y;
 
    return result;
}
 
/*
 ComputeBezier 以控制點 cp 所產生的曲線點,填入 Point2D 結構的陣列。
 呼叫者必須分配足夠的記憶體以供輸出結果,其為 <sizeof(Point2D) numberOfPoints>
*/
 
void ComputeBezier( Point2D* cp, int numberOfPoints, Point2D* curve )
{
    float   dt;
    int	    i;
 
    dt = 1.0 / ( numberOfPoints - 1 );
 
    for( i = 0; i < numberOfPoints; i++)
        curve[i] = PointOnCubicBezier( cp, i*dt );
}

 

在Blend中设计WPF和Silverlight时,我们会经常看到下面方式,设置使用的就是三次方贝塞尔曲线

 

image

 

参考资料:

贝塞尔曲线
http://zh.wikipedia.org/zh-cn/%E8%B2%9D%E8%8C%B2%E6%9B%B2%E7%B7%9A

贝塞尔曲线
http://baike.baidu.com/view/60154.htm

二次贝塞尔曲线实例
http://www.flashas.net/as/20091015/4624.html

posted on 2010-01-22 15:26:21 by ghj1976  评论(1) 阅读(2047)

 

效果如下:

代码简单说明:

海面是通过一个Path来实现的,我们通过故事板来修改Path的贝塞尔曲线的点就可以实现这个效果。当然这个东西如果用代码实现,非常麻烦,好在我们可以用Blend方便的设计出这个特效。

完整代码:

<UserControl x:Class="SilverlightApp_Surf.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="200" d:DesignWidth="640">
    <Canvas RenderTransformOrigin="0.5,0.5" >
        <Canvas.RenderTransform>
            <TransformGroup>
                <ScaleTransform ScaleX="1.0" ScaleY="1" x:Name="Scale"/>
                <SkewTransform AngleX="0" AngleY="0"/>
                <RotateTransform Angle="0"/>
                <TranslateTransform X="0" Y="0" x:Name="Translation"/>
            </TransformGroup>
        </Canvas.RenderTransform>
        <Canvas.Triggers>
            <EventTrigger >
                <BeginStoryboard>
                    <Storyboard RepeatBehavior="Forever" AutoReverse="True">
                        <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Wave" 
                                                      Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[2].(BezierSegment.Point2)">
                            <SplinePointKeyFrame KeyTime="00:00:00" Value="484.749503478214,48.4614211008539" KeySpline="0.766,0,0.265,0.991"/>
                            <SplinePointKeyFrame KeyTime="00:00:01" Value="472.99841325265,33.7398233257606" KeySpline="0.641,0,0.094,0.999"/>
                            <SplinePointKeyFrame KeyTime="00:00:01.7000000" Value="482.133751598516,55.9324453754571" KeySpline="0.5,0,0.188,0.983"/>
                        </PointAnimationUsingKeyFrames>
                        <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Wave" 
                                                      Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[2].(BezierSegment.Point3)">
                            <SplinePointKeyFrame KeyTime="00:00:01" Value="513.106656180137,46.7546299392857" KeySpline="0.641,0,0.094,0.999"/>
                            <SplinePointKeyFrame KeyTime="00:00:01.7000000" Value="499.186383177463,42.3922334944287" KeySpline="0.5,0,0.188,0.983"/>
                        </PointAnimationUsingKeyFrames>
                        <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Wave" 
                                                      Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[3].(BezierSegment.Point1)">
                            <SplinePointKeyFrame KeyTime="00:00:00" Value="540.59991701205,19.6227330505653" KeySpline="0.766,0,0.265,0.991"/>
                            <SplinePointKeyFrame KeyTime="00:00:01" Value="564.908523302214,63.5639248274273" KeySpline="0.641,0,0.094,0.999"/>
                            <SplinePointKeyFrame KeyTime="00:00:01.7000000" Value="525.339507767719,21.6260047359191" KeySpline="0.5,0,0.188,0.983"/>
                        </PointAnimationUsingKeyFrames>
                        <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Wave" 
                                                      Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(BezierSegment.Point2)">
                            <SplinePointKeyFrame KeyTime="00:00:00" Value="256.689637283039,7.23634631616016" KeySpline="0.766,0,0.265,0.991"/>
                            <SplinePointKeyFrame KeyTime="00:00:01" Value="248.899873242055,57.1432452148108" KeySpline="0.641,0,0.094,0.999"/>
                            <SplinePointKeyFrame KeyTime="00:00:01.7000000" Value="233.195785457065,-22.4606421224457" KeySpline="0.5,0,0.188,0.983"/>
                        </PointAnimationUsingKeyFrames>
                        <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Wave"                                                       
                                                      Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(BezierSegment.Point3)">
                            <SplinePointKeyFrame KeyTime="00:00:01" Value="295.076580992168,24.6446375615999" KeySpline="0.641,0,0.094,0.999"/>
                            <SplinePointKeyFrame KeyTime="00:00:01.7000000" Value="298.817962124832,21.7698995286644" KeySpline="0.5,0,0.188,0.983"/>
                        </PointAnimationUsingKeyFrames>
                        <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Wave" 
                                                      Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[2].(BezierSegment.Point1)">
                            <SplinePointKeyFrame KeyTime="00:00:00" Value="350.699783207225,60.8478078352592" KeySpline="0.766,0,0.265,0.991"/>
                            <SplinePointKeyFrame KeyTime="00:00:01" Value="341.253288742281,-7.85397009161106" KeySpline="0.641,0,0.094,0.999"/>
                            <SplinePointKeyFrame KeyTime="00:00:01.7000000" Value="364.440138792599,66.0004411797744" KeySpline="0.5,0,0.188,0.983"/>
                        </PointAnimationUsingKeyFrames>
                        <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Wave" 
                                                      Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point2)">
                            <SplinePointKeyFrame KeyTime="00:00:00" Value="111.373548722153,61.3389964335705" KeySpline="0.766,0,0.265,0.991"/>
                            <SplinePointKeyFrame KeyTime="00:00:01" Value="119.007495207789,17.6773995669566" KeySpline="0.641,0,0.094,0.999"/>
                            <SplinePointKeyFrame KeyTime="00:00:01.7000000" Value="143.912099951412,61.4751946548156" KeySpline="0.5,0,0.188,0.983"/>
                        </PointAnimationUsingKeyFrames>
                        <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Wave" 
                                                      Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point3)">
                            <SplinePointKeyFrame KeyTime="00:00:01" Value="160.569841824079,45.703395381752" KeySpline="0.641,0,0.094,0.999"/>
                            <SplinePointKeyFrame KeyTime="00:00:01.7000000" Value="160.569841824079,45.703395381752" KeySpline="0.5,0,0.188,0.983"/>
                        </PointAnimationUsingKeyFrames>
                        <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Wave" 
                                                      Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(BezierSegment.Point1)">
                            <SplinePointKeyFrame KeyTime="00:00:00" Value="199.555871768111,6.74515771784889" KeySpline="0.766,0,0.265,0.991"/>
                            <SplinePointKeyFrame KeyTime="00:00:01" Value="202.132188440369,73.7293911965473" KeySpline="0.641,0,0.094,0.999"/>
                            <SplinePointKeyFrame KeyTime="00:00:01.7000000" Value="177.227583696746,29.9315961086885" KeySpline="0.5,0,0.188,0.983"/>
                        </PointAnimationUsingKeyFrames>
                        <PointAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Wave" 
                                                      Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point1)">
                            <SplinePointKeyFrame KeyTime="00:00:01" Value="2.27346024513245,34.0420770757097"/>
                            <SplinePointKeyFrame KeyTime="00:00:01.7000000" Value="-16.7514460054151,67.9340629439986"/>
                        </PointAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Canvas.Triggers>
        <Canvas.Background>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FFFFFFFF" Offset="0"/>
                <GradientStop Color="#FF9A0000" Offset="1"/>
            </LinearGradientBrush>
        </Canvas.Background>
        <Path x:Name="Wave" Width="649.767" Height="103.169" Stretch="None" Stroke="#FF000000" Canvas.Top="96.952" Canvas.Left="-9.767">
            <Path.Data>
                <PathGeometry>
                    <PathFigure IsClosed="True" StartPoint="2.27346024513245,34.0420770757097">
                        <BezierSegment Point1="2.27346024513245,34.0420770757097" Point2="155.464710245132,34.0420770757097" Point3="155.464710245132,34.0420770757097"/>
                        <BezierSegment Point1="2.27346024513245,34.0420770757097" Point2="303.694710245132,34.0420770757097" Point3="303.694710245132,34.0420770757097"/>
                        <BezierSegment Point1="2.27346024513245,34.0420770757097" Point2="512.674710245132,34.0420770757097" Point3="512.674710245132,34.0420770757097"/>
                        <BezierSegment Point1="2.27346024513245,34.0420770757097" Point2="649.260960245132,34.0420770757097" Point3="649.260960245132,34.0420770757097"/>
                        <LineSegment Point="649.260960245132,102.669338474509"/>
                        <LineSegment Point="2.27346024513245,102.669338474509"/>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
            <Path.Fill>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF406BF6" Offset="1"/>
                    <GradientStop Color="#FF04123C" Offset="0.983"/>
                    <GradientStop Color="#FFFF7100" Offset="0.353"/>
                </LinearGradientBrush>
            </Path.Fill>
        </Path>
    </Canvas>
</UserControl>

posted on 2010-01-22 13:55:27 by ghj1976  评论(1) 阅读(1963)

 
2010年01月21日

下面是Silverlight制作的时钟演示:

代码简单介绍:

旋转一个对象的中心点是可以定义在这个对象之外的。这个演示中, 时针,分针,秒针,盘上的格子,就是把旋转的中心点定义在盘面的中心,然后定义旋转转换而实现的。

比如盘面的格子部分,我们在样式中有如下定义:

<Style x:Key="MarkersBig" TargetType="Rectangle">
    <Setter Property="RenderTransformOrigin" Value="0.5,12.8"/>
    <Setter Property="Fill" Value="White"/>
    <Setter Property="StrokeThickness" Value="0"/>
    <Setter Property="Width" Value="4"/>
    <Setter Property="Height" Value="10"/>
    <Setter Property="Canvas.Left" Value="158"/>
    <Setter Property="Canvas.Top" Value="32"/>
</Style>

在MainPage.xaml的定义就简单成下面方式:

<Rectangle x:Name="MarkersBig00" Style="{StaticResource MarkersBig}"/>
<Rectangle x:Name="MarkersBig30" Style="{StaticResource MarkersBig}" >
	<Rectangle.RenderTransform>
		<TransformGroup>
			<RotateTransform Angle="30"/>
		</TransformGroup>
	</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="MarkersBig60" Style="{StaticResource MarkersBig}" >
	<Rectangle.RenderTransform>
		<TransformGroup>
			<RotateTransform Angle="60"/>
		</TransformGroup>
	</Rectangle.RenderTransform>
</Rectangle>
............
<Rectangle x:Name="MarkersBig330" Style="{StaticResource MarkersBig}" >
	<Rectangle.RenderTransform>
		<TransformGroup>
			<RotateTransform Angle="330"/>
		</TransformGroup>
	</Rectangle.RenderTransform>
</Rectangle>

巧妙利用故事板的Seek来实现按需播放,以秒针为例,MainPage.xaml 中我们的定义如下:

<!-- 秒针  -->
<Path x:Name="SecondHand" Data="M1.75,100 L-0.5,100 L-0.5,0 L2,0 z" Fill="Red" Canvas.Left="158.494" Stretch="Fill"
      RenderTransformOrigin="0.51,1.199" StrokeThickness="0" Canvas.Top="40.05" UseLayoutRounding="False" Height="100" 
Width="2.888"> <Path.RenderTransform> <TransformGroup> <RotateTransform Angle="0"/> </TransformGroup> </Path.RenderTransform> <Path.Resources> <Storyboard x:Name="SecondsHandStoryboard" > <DoubleAnimation From="0" To="360" Duration="00:01:00" RepeatBehavior="Forever" Storyboard.TargetProperty="(Path.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" Storyboard.TargetName="SecondHand"/> </Storyboard> </Path.Resources> </Path> 我们在 Canvas_Loaded 事件中只需要简单的如下代码就完成了秒针位置的播放。
SecondsHandStoryboard.Begin();
SecondsHandStoryboard.Seek(DateTime.Now.TimeOfDay);
原因何在呢?
SecondsHandStoryboard.Seek( 将故事板进行到指定的时间点位置,而我们 DoubleAnimation  故事板中,执行时间是1分钟,一直不间断执行。这样
DateTime.Now.TimeOfDay 的定位就是秒针正确的时间点。

代码:

App.xaml 中样式文件的定义:

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             x:Class="SilverlightApp_Clock.App">
    <Application.Resources>
        
    	<Style x:Key="MarkersBig" TargetType="Rectangle">
    		<Setter Property="RenderTransformOrigin" Value="0.5,12.8"/>
    		<Setter Property="Fill" Value="White"/>
    		<Setter Property="StrokeThickness" Value="0"/>
    		<Setter Property="Width" Value="4"/>
    		<Setter Property="Height" Value="10"/>
			<Setter Property="Canvas.Left" Value="158"/>
			<Setter Property="Canvas.Top" Value="32"/>
    	</Style>
    	<Style x:Key="MarkersSmall" TargetType="Rectangle">
    		<Setter Property="Width" Value="2"/>
    		<Setter Property="Height" Value="6"/>
    		<Setter Property="RenderTransformOrigin" Value="0.5,21.5"/>
    		<Setter Property="Fill" Value="White"/>
    		<Setter Property="StrokeThickness" Value="0"/>
			<Setter Property="Canvas.Left" Value="159"/>
			<Setter Property="Canvas.Top" Value="31"/>
    	</Style>
    	<Style x:Key="TextBlockNum" TargetType="TextBlock">
    		<Setter Property="FontSize" Value="21.333"/>
    		<Setter Property="FontWeight" Value="Bold"/>
    		<Setter Property="TextAlignment" Value="Center"/>
    		<Setter Property="Foreground" Value="White"/>
    	</Style>
        
    </Application.Resources>
</Application>

MainPage.xaml 文件内容 :

<UserControl x:Class="SilverlightApp_Clock.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="320" d:DesignWidth="320">
    <Canvas Loaded="Canvas_Loaded">
        <!-- 盘面 -->
        <Ellipse Fill="Black" Height="300" Canvas.Left="10" Stroke="#FF3F4462" Canvas.Top="10" Width="300" StrokeThickness="15" />
    	<!-- 盘面中心园° -->
        <Ellipse Fill="Black" Height="30" Canvas.Left="145" Stroke="#FF0024F9" StrokeThickness="3" Canvas.Top="145" Width="30"/>
    	<!-- 盘面大格 -->
        <Rectangle x:Name="MarkersBig00" Style="{StaticResource MarkersBig}"/>
		<Rectangle x:Name="MarkersBig30" Style="{StaticResource MarkersBig}" >
    		<Rectangle.RenderTransform>
    			<TransformGroup>
    				<RotateTransform Angle="30"/>
    			</TransformGroup>
    		</Rectangle.RenderTransform>
    	</Rectangle>
		<Rectangle x:Name="MarkersBig60" Style="{StaticResource MarkersBig}" >
    		<Rectangle.RenderTransform>
    			<TransformGroup>
    				<RotateTransform Angle="60"/>
    			</TransformGroup>
    		</Rectangle.RenderTransform>
    	</Rectangle>
		<Rectangle x:Name="MarkersBig90" Style="{StaticResource MarkersBig}" >
    		<Rectangle.RenderTransform>
    			<TransformGroup>
    				<RotateTransform Angle="90"/>
    			</TransformGroup>
    		</Rectangle.RenderTransform>
    	</Rectangle>
		<Rectangle x:Name="MarkersBig120" Style="{StaticResource MarkersBig}" >
    		<Rectangle.RenderTransform>
    			<TransformGroup>
    				<RotateTransform Angle="120"/>
    			</TransformGroup>
    		</Rectangle.RenderTransform>
    	</Rectangle>
		<Rectangle x:Name="MarkersBig150" Style="{StaticResource MarkersBig}" >
    		<Rectangle.RenderTransform>
    			<TransformGroup>
    				<RotateTransform Angle="150"/>
    			</TransformGroup>
    		</Rectangle.RenderTransform>
    	</Rectangle>
		<Rectangle x:Name="MarkersBig180" Style="{StaticResource MarkersBig}" >
    		<Rectangle.RenderTransform>
    			<TransformGroup>
    				<RotateTransform Angle="180"/>
    			</TransformGroup>
    		</Rectangle.RenderTransform>
    	</Rectangle>
		<Rectangle x:Name="MarkersBig210" Style="{StaticResource MarkersBig}" >
    		<Rectangle.RenderTransform>
    			<TransformGroup>
    				<RotateTransform Angle="210"/>
    			</TransformGroup>
    		</Rectangle.RenderTransform>
    	</Rectangle>
        <Rectangle x:Name="MarkersBig240" Style="{StaticResource MarkersBig}" >
    		<Rectangle.RenderTransform>
    			<TransformGroup>
    				<RotateTransform Angle="240"/>
    			</TransformGroup>
    		</Rectangle.RenderTransform>
    	</Rectangle>
		<Rectangle x:Name="MarkersBig270" Style="{StaticResource MarkersBig}" >
    		<Rectangle.RenderTransform>
    			<TransformGroup>
    				<RotateTransform Angle="270"/>
    			</TransformGroup>
    		</Rectangle.RenderTransform>
    	</Rectangle>
		<Rectangle x:Name="MarkersBig300" Style="{StaticResource MarkersBig}" >
    		<Rectangle.RenderTransform>
    			<TransformGroup>
    				<RotateTransform Angle="300"/>
    			</TransformGroup>
    		</Rectangle.RenderTransform>
    	</Rectangle>
		<Rectangle x:Name="MarkersBig330" Style="{StaticResource MarkersBig}" >
    		<Rectangle.RenderTransform>
    			<TransformGroup>
    				<RotateTransform Angle="330"/>
    			</TransformGroup>
    		</Rectangle.RenderTransform>
    	</Rectangle>
        <!-- 盘面小格 -->
		<Rectangle x:Name="MarkersSmall06" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="6"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall12" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="12"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall18" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="18"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall24" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="24"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall36" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="36"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall42" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="42"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall48" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="48"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall54" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="54"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall66" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="66"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>

		<Rectangle x:Name="MarkersSmall72" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="72"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall78" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="78"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall84" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="84"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>

		<Rectangle x:Name="MarkersSmall96" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="96"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall102" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="102"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall108" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="108"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall114" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="114"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall126" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="126"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall132" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="132"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall138" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="138"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall144" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="144"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall156" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="156"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall162" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="162"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall168" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="168"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall174" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="174"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall186" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="186"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall192" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="192"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall198" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="198"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall204" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="204"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall210" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="210"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall216" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="216"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall222" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="222"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall228" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="228"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall234" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="234"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall246" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="246"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall252" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="252"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall258" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="258"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall264" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="264"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall276" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="276"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall282" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="282"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall288" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="288"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall294" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="294"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall306" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="306"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall312" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="312"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall318" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="318"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall324" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="324"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall336" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="336"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall342" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="342"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall348" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="348"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
		<Rectangle x:Name="MarkersSmall354" Style="{StaticResource MarkersSmall}">
			<Rectangle.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="354"/>
				</TransformGroup>
			</Rectangle.RenderTransform>
		</Rectangle>
        <!-- 盘面数字显示 -->
		<TextBlock x:Name="tb_1" Canvas.Left="207" Canvas.Top="64" Style="{StaticResource TextBlockNum}">1</TextBlock>
		<TextBlock x:Name="tb_2" Canvas.Left="241" Canvas.Top="102" Style="{StaticResource TextBlockNum}">2</TextBlock>
		<TextBlock x:Name="tb_3" Canvas.Left="253" Canvas.Top="145" Style="{StaticResource TextBlockNum}">3</TextBlock>
		<TextBlock x:Name="tb_4" Canvas.Left="240" Canvas.Top="194" Style="{StaticResource TextBlockNum}">4</TextBlock>
		<TextBlock x:Name="tb_5" Canvas.Left="205" Canvas.Top="227" Style="{StaticResource TextBlockNum}">5</TextBlock>
		<TextBlock x:Name="tb_6" Canvas.Left="153" Canvas.Top="238" Style="{StaticResource TextBlockNum}">6</TextBlock>
		<TextBlock x:Name="tb_7" Canvas.Left="106" Canvas.Top="227" Style="{StaticResource TextBlockNum}">7</TextBlock>
		<TextBlock x:Name="tb_8" Canvas.Left="71" Canvas.Top="194" Style="{StaticResource TextBlockNum}">8</TextBlock>
		<TextBlock x:Name="tb_9" Canvas.Left="54" Canvas.Top="145" Style="{StaticResource TextBlockNum}">9</TextBlock>
		<TextBlock x:Name="tb_10" Canvas.Left="64" Canvas.Top="96" Style="{StaticResource TextBlockNum}">10</TextBlock>
		<TextBlock x:Name="tb_11" Canvas.Left="99" Canvas.Top="63" Style="{StaticResource TextBlockNum}">11</TextBlock>
		<TextBlock x:Name="tb_12" Canvas.Left="145" Canvas.Top="50" Style="{StaticResource TextBlockNum}">12</TextBlock>
        <!-- 显示年月日 -->
	<TextBlock x:Name="tb_YearMonthDay" Height="19" Canvas.Left="123" TextWrapping="Wrap" Text="2010-01-20" Canvas.Top="204" Width="74" Style="{StaticResource TextBlockNum}" FontSize="10.667"/>
	<!-- 秒针  -->
        <Path x:Name="SecondHand" Data="M1.75,100 L-0.5,100 L-0.5,0 L2,0 z" Fill="Red" Canvas.Left="158.494" Stretch="Fill"
              RenderTransformOrigin="0.51,1.199" StrokeThickness="0" Canvas.Top="40.05" UseLayoutRounding="False" Height="100" Width="2.888">
			<Path.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="0"/>
				</TransformGroup>
			</Path.RenderTransform>
            <Path.Resources>
                <Storyboard x:Name="SecondsHandStoryboard"  >
                    <DoubleAnimation From="0" To="360" Duration="00:01:00" RepeatBehavior="Forever" 
								Storyboard.TargetProperty="(Path.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" 
                                     Storyboard.TargetName="SecondHand"/>
                </Storyboard>
            </Path.Resources>
        </Path>
        <!-- 分针  -->
		<Path x:Name="MinuteHand" Data="M3.8847754,100.055 L-1.3659742,100.055 L-0.5036189,40.723522 L2.4733605,40.545193 z" Fill="#FFB9DA12" Canvas.Left="157.238" RenderTransformOrigin="0.545,1.333" Stretch="Fill" StrokeThickness="0" Canvas.Top="80.486" UseLayoutRounding="False" Height="59.511" Width="5.25">
			<Path.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="30"/>
				</TransformGroup>
			</Path.RenderTransform>
            <Path.Resources>
                <Storyboard x:Name="MinuteHandStoryboard"  >
                    <DoubleAnimation From="0" To="360" Duration="01:00:00" RepeatBehavior="Forever" 
								Storyboard.TargetProperty="(Path.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" Storyboard.TargetName="MinuteHand"/>
                </Storyboard>
            </Path.Resources>
        </Path>
        <!-- 时针  -->
		<Path x:Name="HourHand" Data="M3.8847754,100.055 L-1.3659742,100.055 L-0.62599868,41.085041 L2.9391243,41.085041 z" Fill="#FFB9DA12" Canvas.Left="156.393" RenderTransformOrigin="0.459,1.536" Stretch="Fill" StrokeThickness="0" Canvas.Top="102.667" UseLayoutRounding="False" Height="37.333" Width="7.855">
			<Path.RenderTransform>
				<TransformGroup>
					<RotateTransform Angle="0"/>
				</TransformGroup>
			</Path.RenderTransform>
            <Path.Resources>
                <Storyboard x:Name="HourHandStoryboard"  >
                    <DoubleAnimation From="0" To="360" Duration="12:00:00" RepeatBehavior="Forever" 
								Storyboard.TargetProperty="(Path.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" Storyboard.TargetName="HourHand"/>
                </Storyboard>
            </Path.Resources>
        </Path>
    </Canvas>
</UserControl>

MainPage.xaml.cs 文件内容:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightApp_Clock
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }


        private void Canvas_Loaded(object sender, RoutedEventArgs e)
        {
            DateTime dt = DateTime.Now;
            this.tb_YearMonthDay.Text = dt.ToString("yyyy-MM-dd");

            SecondsHandStoryboard.Begin();
            SecondsHandStoryboard.Seek(dt.TimeOfDay);
            MinuteHandStoryboard.Begin();
            MinuteHandStoryboard.Seek(dt.TimeOfDay);
            HourHandStoryboard.Begin();
            HourHandStoryboard.Seek(dt.TimeOfDay);
        }
    }
}

参考资料:

Clock C#
http://silverlight.net/community/samples/details.aspx?__itemid=15784

Hybrid Clock for Microsoft Silverlight 2.0
http://www.alexanderbell.us/HybridClock.htm

Developing Silverlight Analog Clock - pattern oriented approach
http://www.silverlightshow.net/items/Developing-Silverlight-Analog-Clock-pattern-oriented-approach.aspx

Developing Silverlight AnalogClock – part 2 – Enhancing the view
http://www.silverlightshow.net/items/Developing-Silverlight-AnalogClock-part-2-Enhancing-the-view.aspx

posted on 2010-01-21 18:03:26 by ghj1976  评论(1) 阅读(1029)

 
2010年01月20日

OpenSocial 可为跨多个网站的社交应用程序定义通用 API。最典型的就是获得用户的好友信息。Siverlight 在用户体验方面又可以做出很酷的应用。这两者一旦结合,做出来的应用应该很有市场。

 

下面就是一个简单的演示。

演示修改自 Michael S. Scherotter 写的例子:

主要修改是:

由于CSDN支持的 opensocial 是 0.9, 而 Michael S. Scherotter 写的例子写的列子是基于opensocial 是 0.5 的, 对应的获得好友信息等的代码修改成使用最新的API: osapi 。

Michael S. Scherotter 写的例子可以在下面地址获得:

http://hosting.gmodules.com/ig/gadgets/file/113009390747258006757/SilverlightOpenSocial.xml

 

我写的例子代码可以在下面地址获得:

http://ghj1976.blob.core.windows.net/silverlight/SilverlightOpenSocial.xml 

 

程序执行的效果截图如下:

image

有 CSDN 帐号的,也可以通过CSDN 的个人空间安装这个应用。

 

参考资料:

MySpace supports Silverlight for OpenSocial apps
http://www.itworld.com/development/65364/myspace-supports-silverlight-opensocial-apps

Silverlight Kit for MySpace
http://myspacesilverlight.codeplex.com/

Microsoft Silverlight Jives With Google's OpenSocial
http://silverlight.sys-con.com/node/454864 

Silverlight in MySpace via OpenSocial
http://blogs.msdn.com/synergist/archive/2008/02/06/silverlight-in-myspace-via-opensocial.aspx

posted on 2010-01-20 16:53:19 by ghj1976  评论(0) 阅读(1897)

 
2010年01月19日

之前我一直在使用 http://silverlight.live.com/ 作为我开发的 silverlight 免费存储空间, 最近这里看到将在2010年1月31号就将停止。在上述地址提供的推荐替代方案是使用 Windows Azure

Azure 的价格表,请参看: http://www.microsoft.com/windowsazure/offers/ 其中免费的可以提供500M的空间,如下图:

image

如何申请 Azure ,并部署 Silverlight Application ,有很多博客都写到的,下面就是一些这样的博客:

不用工具,10分钟内在Windows Azure部署Silverlight Application:
http://colinizer.com/2009/12/14/deploy-this-silverlight-application-on-windows-azure-in-10-minutes-no-tools-required/

Hosting Videos on Windows Azure
http://blogs.msdn.com/david_sayed/archive/2010/01/07/hosting-videos-on-windows-azure.aspx

Using Azure as a Silverlight Streaming replacement
http://timheuer.com/blog/archive/2009/11/30/using-windows-azure-to-replace-silverlight-streaming-howto.aspx

Creating and Publishing a Silverlight Video to Windows Azure
http://blogs.msdn.com/david_sayed/archive/2010/01/07/creating-and-publishing-a-silverlight-video-to-windows-azure.aspx

Setting up Windows Azure for video storage
http://blogs.msdn.com/david_sayed/archive/2010/01/07/setting-up-windows-azure-for-video-storage.aspx

 

为了更方便的使用 Azure, 下面有几个工具推荐,都是免费的:

Azure Storage Explorer  , 协助我们在 Azure 上存取文件的工具,下载地址如下:
http://azurestorageexplorer.codeplex.com/

 

Windows Live Writer 嵌入Azure 的 Silverlight Application,并嵌入博客的插件:
http://gallery.live.com/liveItemDetail.aspx?li=f84d87b9-e284-4691-aa90-2d628e67af6f&pl=8&bt=9

对这个插件的介绍博客:
Azure Blob Storage plugin for Windows Live Writer now available
http://www.clarkezone.net/default.aspx?id=395b2013-40c3-4459-9824-43890bde7b2c

Embedding a Silverlight Video in a Blog
http://blogs.msdn.com/david_sayed/archive/2010/01/07/embedding-a-silverlight-video-in-a-blog.aspx 

 

参考资料:

如何在Windows Azure上托管SilverLight应用
http://blogs.msdn.com/yananwu/archive/2009/04/04/windows-azure-silverlight.aspx

 

下面就是我嵌入的一个演示:使用的是 iframe

<iframe style="width: 500px; height: 180px" 
src=http://ghj1976.blob.core.windows.net/silverlight/TwoWayBindingTestPage.html
frameborder="0" scrolling="no"></iframe>

posted on 2010-01-19 15:26:17 by ghj1976  评论(1) 阅读(2055)

 
2010年01月14日

OOB (Out of Browser) 是 Silverlight 3 开始支持的一个新特性,可以让 Silverlight 向 Windows 普通程序那样运行。

如何编写支持OOB特性的程序,需要注意下面三点:

  • 配置 Silverlight 应用,以便使它可以运行在离线模式下,即: 修改 AppManifest.xml 文件,完成这个设置。
  • 程序启动时,检查是否运行在OOB方式下。
  • 只有网络可用时,再加载和存储本地或远程数据。

 

配置成离线:

下图为 VS2010 项目属性中, 我们可以打开 Silverlight项目的 OOB 功能。

image 

 

选中后,我们就可以设置 OOB 的一些细节,如下图:

image

 

Blend 中的设置在下面:

image

 

 

配置好上面步骤后,我们在通过网页访问这个 Silverlight 应用时,右键菜单中就是下面菜单项:

image

选择安装到此计算机菜单项后,就会有下面的设置选项:

image

成功安装后,以 OOB 方式运行时,右键菜单中就有卸载的选项,如下图:

image

检测是否运行在OOB 模式下

可以用下面代码实现这个检测:

// 检测离线应用
if (Application.Current.RunningOffline)
{
    // Launched in sllauncher.exe
}
else
{
    // Launched in a browser
}

检测网络状态

可以用下面代码实现这个检测:

//  检测网络是否可用的代码
if(NetworkInterface.GetIsNetworkAvailable())
{
    // App is connected
}
else
{
    // App is not connected
}

 

参考资料:

Silverlight 3 OOB
http://www.mdong.org/?p=828
http://www.mdong.org/?p=836

Silverlight 3.0 OOB 原理开发及离线文件存储位置
http://blog.csdn.net/chinull/archive/2009/10/04/4632650.aspx

posted on 2010-01-14 16:39:07 by ghj1976  评论(0) 阅读(1984)

 
2010年01月11日

今天在处理一个用户名数据库时,发现有些不正常的数据存在,按照逻辑,用户名只能是数字,字母,下划线和纯中文这样的字符组合存在,不应该有其他组合存在,但是发现数据库中由于各种历史原因,有些不正常的存在,如何找到这些异常数据,在CSDN的 SQL Server 版问了这样两个问题,如下:

http://topic.csdn.net/u/20100111/14/529a21a1-3ea8-4263-a0d9-34e83be79b1d.html

http://topic.csdn.net/u/20100111/15/c2a124c5-bc5b-4626-86ce-c5b862cf5cff.html

感谢CSDN的网友帮忙解决了这个问题,下面就是解决方法的汇总:

if object_id('[t1]') is not null 
	drop table [t1]
create table [t1]([c] nvarchar(20))

insert [t1]
select 'aaa' union all		-- 此数据不应该被搜索到
select 'bcds' union all		-- 此数据不应该被搜索到
select 'a1' union all		-- 此数据不应该被搜索到
select '' union all		-- 此数据不应该被搜索到
select '^%' union all		-- 应该搜索到
select 'ew1' union all		-- 此数据不应该被搜索到
select '344' union all		-- 此数据不应该被搜索到
select '__' union all		-- 此数据不应该被搜索到
select '213_21' union all	-- 此数据不应该被搜索到	
select 'a_2' union all		-- 此数据不应该被搜索到
select 'd' union all		-- 此数据不应该被搜索到
select 'ddd' union all		-- 此数据不应该被搜索到
select '电风扇' union all	-- 此数据不应该被搜索到
select '★思寒★' union all	-- 应该搜索到
select 'Ω' union all	        -- 应该搜索到
select 'トントン' union all	-- 应该搜索到
select '***' union all	        -- 应该搜索到
select '///////' union all	-- 应该搜索到
select '@-@' union all	        -- 应该搜索到
select '@小慧' union all	        -- 应该搜索到
select '~*晓菊*~' union all	-- 应该搜索到
select '啊★洛' union all	-- 应该搜索到
select '不思議の夜' union all	-- 应该搜索到
select '(嘉宾)胡飞' union all	-- 应该搜索到
select '--------------'		-- 应该搜索到



select * from [t1] WHERE PATINDEX('%[0-9a-z_]%',c)=0 
and PATINDEX('%[^吖-座]%',c) <> 0

 

另外感慨一下,CSDN的 SQL Server 版 问出问题到解决问题,竟然比Google 搜索答案还要快, SQL Server 版 的牛人真多, 而且回答的这么快,实在让人吃惊。

posted on 2010-01-11 15:41:38 by ghj1976  评论(0) 阅读(2182)

 

一般来说,在您将 Web 应用 正式部署于生产环境前,它已经被用于多个环境了。这些环境可能包括: 开发人员开发环境、质量保证 (QA) 以及用户验收测试 (UAT)/暂存/预生产环境。在这些环境中转换应用程序时,配置文件中的很多设置都必须更改。比如:数据库链接字符串的配置,文件存放位置,服务器的地址和端口等。

VS2010 中通过提供 XML-Document-Transform engine 来帮我们解决这个问题。

要使用XML-Document-Transform engine就要先引用XML-Document-Transform 命名空间。如下面代码所示:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">

转换的工作原理:

当 Microsoft Visual Studio 2010 编译时,编译器会自动根据当前选择的编译选项,选择对应的web.编译选项名.config和web.config 进行合并转换,继而产生对应部署环境的 web.config 文件,如下图所示:

 

image

上图中,我们可以看到有2个关键属性:

  • xdt:Transform
  • xdt:Locator

这两个属性可以设置的值是一下几种类型:

转换 描述
xdt:Transform=“Replace” 替换第一个匹配的节点
xdt:Transform=“Remove” 清除第一个匹配的节点
xdt:Transform=“RemoveAll” 清除所有匹配的节点
xdt:Transform=“Insert” 在末尾插入节点
xdt:Transform=“SetAttributes(attributeNames)” 创建或更改现有属性的值
xdt:Transform=“RemoveAttributes(attributeNames)” 清除属性(如果有)
xdt:Transform=“InsertBefore(XPath)” 在指定Xpath前插入节点
xdt:Transform=“InsertAfter(XPath)” 在指定Xpath后插入节点

定位符 描述
xdt:Locator=“Match(attributeName)” 可以使用逗号分隔属性名称
xdt:Locator=“Condition(xPath Predicate)” 可以接受任何 Xpath 谓词,如xdt:Locator="Condition(@name=’Northwind’ or @providerName=’ System.Data.SqlClient’)"
xdt:Locator=“Xpath(/configuration/…)” 可以接受任何复杂的 Xpath,如 "XPath(//system.web)"

下面是一个简单的实例:

如下图所示,我们在一个 Web 项目中, 配置编译选项:

image

我们新建一个,按照我们自己发布情况定义的编译选项:

image

如下图所示,我们建立一个本地部署测试环境的配置, 注意,这里默认就选中了 Create new project configurations

image

在 Solution Explorer 中选中 Web.config ,在右键菜单中点击:“Add Config Transforms” 项,如下图:

 image

我们就可以看到多了一个“Web.LocalDeploy.config” 文件:

image

为了测试期间,我们 web.config 文件有以下设置:

<configuration>
  <appSettings>
    <add key="KeyOne" value="A value"/>
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />

Web.LocalDeploy.config 文件有以下设置:

<?xml version="1.0"?>
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add key="KeyOne" value="B Value" xdt:Transform="Replace" xdt:Locator="Match(key)"/>
  </appSettings>
  <!--
    In the example below, the "SetAttributes" transform will change the value of 
    "connectionString" to use "ReleaseSQLServer" only when the "Match" locator 
    finds an atrribute "name" that has a value of "MyDB".
    
    <connectionStrings>
      <add name="MyDB" 
        connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" 
        xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </connectionStrings>
  -->
  <system.web>
    <compilation xdt:Transform="RemoveAttributes(debug)" />
    <!--
      In the example below, the "Replace" transform will replace the entire 
      <customErrors> section of your web.config file.
      Note that because there is only one customErrors section under the 
      <system.web> node, there is no need to use the "xdt:Locator" attribute.
      
      <customErrors defaultRedirect="GenericError.htm"
        mode="RemoteOnly" xdt:Transform="Replace">
        <error statusCode="500" redirect="InternalError.htm"/>
      </customErrors>
    -->
  </system.web>
</configuration>

从 Web.LocalDeploy.config 文件我们可以看到, 我们使用 LocalDeploy 发布时,要求修改 appSettings 属性 KeyOne 的值,同时,删除 compilation 中打开 debug 的功能。

之后,我们发布项目时, 就会自动产生对应的配置文件,发布选项如下:

image

为了简单起见,这里是发布到另外一个目录,我们在  D:\123\1 目录下查看 web.config 文件,就可以看到是下面的信息:

<configuration>
  <appSettings>
    <add key="KeyOne" value="B Value"/>
  </appSettings>
  <system.web>
    <compilation targetFramework="4.0" />

 

小结:

通过 ASP.net 4.0 新特性:Web.Config Transformation,我们可以自动产生不同使用环境下的 web.config。很强大,不错。

但是这跟我的期望还是有点差异,比如有些时候,我的配置并不在 web.config 文件中,就使用不到这个新特性。

另外在开发环境模拟部署环境的测试, 还是要手工修改 web.config 文件。而不能力用到这个特性。


参考资料:

ASP.Net4.0中新增23项功能
http://www.cnblogs.com/zhuqil/archive/2010/01/05/1639405.html (中文翻译)
http://www.codeproject.com/KB/aspnet/Whatis_New_ASP_Net_4.aspx (英文原文)

ASP.NET 4.0 新特性--Web.Config Transformation
http://www.cnblogs.com/worksguo/archive/2009/08/29/1556307.html

Web.config 转换概览(Transformation Overview)
http://www.cnblogs.com/Intersense/archive/2009/12/25/1632212.html

Web.config Transformation Overview
http://msdn.microsoft.com/zh-cn/library/dd465326(en-us,VS.100).aspx

Visual Studio 2010 中的 Web 开发
http://msdn.microsoft.com/zh-cn/library/ee851840.aspx

Web Deployment: Web.Config Transformation
http://blogs.msdn.com/webdevtools/archive/2009/05/04/web-deployment-web-config-transformation.aspx

Visual Studio 2010: Web.config transforms
http://weblogs.asp.net/gunnarpeipman/archive/2009/06/16/visual-studio-2010-web-config-transforms.aspx

posted on 2010-01-11 10:34:15 by ghj1976  评论(2) 阅读(2377)

 
2010年01月07日

前面一篇博客“WPF/Silverlight 控件的基本组成” 介绍了创建控件模板的一些基础知识,这篇是一个简单演示,演示一个不规则的按钮。

为了简单期间,我们只定义了按钮的鼠标移动到上面以及鼠标点击两个特效。其他特效没有定义。

演示效果如下:

对应Xaml代码,代码中已经增加了注释,如果前一篇博客阅读过,对代码的阅读就没有难度,代码如下:

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	x:Class="SilverlightApplication_IrregularButton.MainPage"
	Width="250" Height="150" mc:Ignorable="d">
	<UserControl.Resources>
		<!-- 模板定义 //-->
		<ControlTemplate x:Key="ButtonControlTemplate1" TargetType="Button">
			<Grid>
				<VisualStateManager.VisualStateGroups>
					<VisualStateGroup x:Name="FocusStates">
						<VisualState x:Name="Focused"/>
						<VisualState x:Name="Unfocused"/>
					</VisualStateGroup>
					<VisualStateGroup x:Name="CommonStates">
						<VisualState x:Name="Normal"/>
						
						<VisualState x:Name="MouseOver">
							<!-- 当鼠标滑动到上面时,不规则按钮放大,以显示当前在这个按钮上//-->
							<Storyboard>
								<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="path" 
								Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
									<EasingDoubleKeyFrame KeyTime="00:00:00" Value="1.1"/>
								</DoubleAnimationUsingKeyFrames>
								<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="path" 
								Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
									<EasingDoubleKeyFrame KeyTime="00:00:00" Value="1.1"/>
								</DoubleAnimationUsingKeyFrames>
							</Storyboard>
						</VisualState>
						<VisualState x:Name="Pressed">
							<!-- 当鼠标按下时,不规则按钮颜色变深,表示点击了 //-->
							<Storyboard>
								<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="path" 
								Storyboard.TargetProperty="(UIElement.OpacityMask).(GradientBrush.GradientStops)[0].(GradientStop.Offset)">
									<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0.4"/>
								</DoubleAnimationUsingKeyFrames>
							</Storyboard>
						</VisualState>
						<VisualState x:Name="Disabled"/>
					</VisualStateGroup>
				</VisualStateManager.VisualStateGroups>
				
				<Path x:Name="path"   Stretch="Fill" 
					Stroke="{TemplateBinding BorderBrush}" 
					StrokeThickness="2" Margin="10.652,1.073,8,0" 
					UseLayoutRounding="False" 
					Data="M36.891956,9.7781897 C64.593346,-11.270991 79.772194,-3.6822519 95.642052,17.778385 C176.95827,
					15.002772 153.51022,23.269783 98.359367,44.312874 C81.101433,49.818928 46.730473,42.151268 47.980583,
					38.40152 C28.298779,43.241684 7.1613593,35.330677 36.891956,9.7781897 z" 
					RenderTransformOrigin="0.5,0.5" Fill="{TemplateBinding Background}" >
					<Path.OpacityMask>
						<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
							<GradientStop Color="White" Offset="1"/>
							<GradientStop Color="#26FFFFFF"/>
						</LinearGradientBrush>
					</Path.OpacityMask>
				
					<Path.RenderTransform>
						<TransformGroup>
							<ScaleTransform/>
							<SkewTransform/>
							<RotateTransform/>
							<TranslateTransform/>
						</TransformGroup>
					</Path.RenderTransform>					
				</Path>
				<ContentPresenter Margin="33,18,72,18"/>
			</Grid>
		</ControlTemplate>
		<!-- 定时默认样式 //-->
		<Style x:Key="IrregularButton" TargetType="Button">
			<Setter Property="Template" Value="{StaticResource ButtonControlTemplate1}"/>
			<Setter Property="Background" Value="#FFA56B16"/>
			<Setter Property="Foreground" Value="#FF000000"/>
		</Style>
	</UserControl.Resources>

	<Grid x:Name="LayoutRoot" Background="White">
		<!-- 使用样式定义的按钮 //-->
		<Button  Style="{StaticResource IrregularButton}"
		Content="Button1" Foreground="#FF2431C2" Background="#FFBA730A" BorderBrush="#FF111695" Height="70"  Width="180"/>
	</Grid>
</UserControl>

 

参考资料:

Silverlight2 边学边练 之七 模板与状态
http://www.cnblogs.com/gnielee/archive/2009/08/03/1537929.html

一步一步学Silverlight 2系列(9):使用控件模板
http://www.cnblogs.com/Terrylee/archive/2008/03/08/Silverlight2-step-by-step-part9-using-control-template.html

理解silverlight 2.0中的Templated Control
http://silverlight.cn/index.php?q=node/597

演练:使用 ControlTemplate 自定义按钮的外观
http://msdn.microsoft.com/zh-cn/library/cc903963(VS.95).aspx

Control Templates
http://silverlight.net/learn/quickstarts/controltemplates/

通过使用 ControlTemplate 自定义现有控件的外观
http://msdn.microsoft.com/zh-cn/library/cc189093(VS.95).aspx

创建系统控件的可重用模板
http://msdn.microsoft.com/zh-cn/library/dd185509.aspx

posted on 2010-01-07 16:54:30 by ghj1976  评论(0) 阅读(2089)

 

WPF/Silverlight 的控件实现分逻辑和模板两个部分:以 Button 控件为例,如下图所示,他们之间通过 DataBinding 来协作。

image

上图来自:http://www.wpftutorial.net/Templates.html 

 

每个控件都有一个默认模板,以展示控件的基本外观。我们在Blend中,选中控件,在右键菜单中点击, 编辑模板 --》 编辑副本 。如下图,然后查看Xaml文件,我们就可以看到这个控件的默认模板Xaml代码。

image

 

对于控件模板的定义,有两种方式。

一种是 : Styling (Styles)。

对控件作一些小的视觉改变,比如:背景,字体等。

 

image

一个简单例子:

<Grid>
  <Grid.Resources>
    <Style x:Key="ButtonStyle" TargetType="Button">
      <Setter Property="Foreground" Value="Gray"/>
      <Setter Property="Background" Value="Purple"/>
      <Setter Property="FontStyle" Value="Italic"/>
      <Setter Property="FontFamily" Value="Cool.tff#Cool"/>
    </Style>
  </Grid.Resources>
  <Button Width="100" Height="50"
     Style="{StaticResource ButtonStyle}" 
     Content="Button" />
</Grid>

更多样式的知识可以参看下面这篇我的博客: Silverlight 样式

另外一种是:Skinning (Control Templates)

Control Templates 可以不改变控件基本行为前提下,重新定义控件的全部视觉树(Visual Tree),以替换原先默认的视觉树(Visual Tree)。

image

Control Templates 又包括两部分:

  • look(外观),具体的展示外形。
  • feel(感觉),指一些改变发生时,交互的响应性。例如,在按下时、得到焦点时、失去焦点时、处于按下的状态时、处于不可用(disabled)状态时、内中有东西被选中时等等,它是如何反应的。我们经常地在用户象这样与控件做交互时,要执行动画效果。

 

先看look(外观)的一个简单例子:

<Grid>
  <Grid.Resources>
    <!-- Button Template -->
    <ControlTemplate x:Key="ButtonTemplate" TargetType="Button">
      <Grid>
	 <Path Data="M204,230 C208.84642,220.30716 211.16937,182.25732 225,
		  181 C248.57742,178.8566 242.08521,174.47534 258,201 C285.81909,173.18089 
		  251.23732,170 304,170 C317.57971,170 346.71796,167.80339 325,204 C338.91797,
		  201.68034 353.5448,203 368,203 C376.44458,203 377.05286,204.36786 370,222 
		  C359.54306,248.14235 356.68863,237 327,237 C331.94324,246.88651 338,251.45328 
		  338,263 C338,273.60532 336.69473,276.65265 326,282 C310.42996,289.78503 287,
		  287.73874 287,251 C281.99072,255.00742 234.25241,285.26208 229,259 C226.8019,
		  248.00948 241.02324,242.00388 223,239 C203.01422,235.66904 215.56958,244.12169 204,230 z" 
		Fill="{TemplateBinding Background}" Stretch="Fill" Stroke="#FFF77474" />
			  
         <ContentPresenter Margin="30"/>
      </Grid>
     </ControlTemplate>
  </Grid.Resources>

  <!-- Button -->
  <Button Content="Button" 
          Template="{StaticResource ButtonTemplate}" Width="100" Height="80" Margin="263,202,277,198">
    <Button.Background>
      <RadialGradientBrush>
        <GradientStop Color="#FFF4A1A1"/>
        <GradientStop Color="#FFBD2121" Offset="1"/>
      </RadialGradientBrush>
    </Button.Background>
  </Button>
</Grid>

执行效果截图:

image

上面的Xaml 文件中,我们可以看到Control Templates和控件逻辑的数据绑定,是通过下面几种方式进行的

  • 使用 {TemplateBinding} 来进行控件的属性和模板的数据绑定;
  • 使用 ContentPresenter 和 ItemsPresenter 来进行控件内容和模板的数据绑定;

你可以在上面例子看到,我们的按钮控件现在拥有一个比较好看的外观。尽管它有了一个新的外观,但按钮依然象以前那样触发同样的焦点,点击,和悬浮事件。所以,使用按钮的开发人员在使用了我们的新控件模板的按钮后,不用改动任何代码,就可以修改外观。

但我们的新按钮控件模板的一个缺点是,它并不是交互的。这意味着,如果按钮获得/失去焦点,或者鼠标悬浮其上时,我得不到任何视觉反馈。点击时,我也得不到很好的按下/弹起的动画效果。 这就涉及到 feel(感觉) 。

 

对于  Control Templates 来说,feel(感觉),就是控件的状态变化时,在人机交互上如何给予体现。一般是通过用户定义的一个个动画来展示的。管理这些状态变化的就叫:Visual State Manager。

Visual State Manager (VSM-视觉状态管理器)包括2个部分:

  • Visual States (视觉状态), 例如,按钮这样的控件为自己定义了多个视觉状态: Normal(正常), MouseOver(鼠标在此之上), Pressed(按下), Disabled(不可用), Focused(获取焦点), Unfocused(不具焦点)。
  • Visual Transitions (视觉转换过度),

以 Button 为例,在 Blend 中如果我们修改 Button  默认的 Control Templates 时,会看到它有以下几种状态及状态分组。

image

下面是按钮的默认模板时,FocusStates 状态组的 Xaml 代码。

<VisualStateGroup x:Name="FocusStates">
	<VisualState x:Name="Focused">
		<Storyboard>
			<DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
				<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
			</DoubleAnimationUsingKeyFrames>
		</Storyboard>
	</VisualState>
	<VisualState x:Name="Unfocused"/>
</VisualStateGroup>

上述写法表示:

  • 同一状态组内是互斥的几个状态,即,上面例子中,按钮只能是获得焦点或者没有获得焦点状态之一,不能同时是这两个状态。
  • VisualState 类具有更改控件外观的 Storyboard 属性。控件进入 VisualState.Name 属性指定的状态时,Storyboard 开始。控件退出该状态时,Storyboard 停止。上面例子中,当按钮获得焦点时,FocusVisualElement 的 Opacity 变成 1。这时候的状态过度相当于下面选择的那个。

image

    

参考资料:

Control Templates
http://www.wpftutorial.net/Templates.html

谈谈Silverlight 2中的视觉状态管理 Part1 
http://www.cnblogs.com/Terrylee/archive/2008/07/08/silverlight-2-visual-state-manager-part-1.html

谈谈Silverlight 2中的视觉状态管理 Part2
http://www.cnblogs.com/Terrylee/archive/2008/08/14/silverlight-2-visual-state-manager-part-2.html

使用Blend开发Silverlight VSM
http://blog.joycode.com/scottgu/archive/2008/06/09/115138.joy

Customized Control 和 User Control
http://www.cnblogs.com/winter-cn/archive/2009/02/14/1390420.html

posted on 2010-01-07 13:15:34 by ghj1976  评论(0) 阅读(1905)

 
2010年01月05日

这篇是以 Blend 设计工具上的功能按钮为线索来介绍几种Silverlight 图形的转换。转换一般不影响布局,通常是在动画处理或向元素应用添加临时效果时用。

变化中心点的定义

变化的中心点在Blend工具上有2个地方定义:

一个是可以通过鼠标点击就可以使用的9个常用位置,

如下图的 image 就是。我们可用鼠标来点击这9个点,对应设置这个元素的中心位置。

image

对应到Xaml 文件中,就是修改选择元素的 RenderTransformOrigin 属性。

UIElement.RenderTransformOrigin 属性用于获取或设置由 RenderTransform 声明中,任何可能导致转换的中心点,这个中心点是相对于元素的边界而言的。

设置的值类似: RenderTransformOrigin="0.5,1", 依次是水平原点因子,垂直原点因子。通常这两个值为 0 至 1 之间的值。

0 和 1 之间的值被解释为当前元素在每个 X 轴和 Y 轴上的范围的因子。例如,(0.5,0.5) 将使呈现转换位于元素中心,而 (1,1) 会将呈现转换置于元素的右下角。

默认值是一个坐标为 (0,0) 的 Point。即: image

RenderTransformOrigin 也可以接受 0 和 1 以外的值,并且将导致更不寻常的转换效果。例如,如果将 RenderTransformOrigin 设为 (5,5),然后应用 RotateTransform,则旋转点将位于元素自身边界之外。转换将沿圆心远在右下方的大圆旋转元素。原点可能位于其父元素的某处,并可能位于框架或视图之外。负点值与此类似,这将超出左上边界。

Blend 中另外一个设置中心点的位置如下:在这里我们可以更灵活的设置,而不是之前的9个固定的常用点。

image

 

 

平移 TranslateTransform

沿 X、Y 平移对象 跟定义常用的9个中心点在同一界面,如下:

image

上图中,指定元素按照X轴移动10个像素 ,Y轴移动10个像素。这两个属性的默认值都是0。可以为正值,可以为负值,可以为非整数。比如下面设置就是可以的

<TranslateTransform X="-10.842" Y="7.468"/>

上面图片中,当我们把“使用相对值”打上勾时,表示我们要在目前平移数据上再相对增加的值,这时候输入相对值后,需要点击应用才会起作用。

在输入数字框里面,我们使用滚轮,也可以自动增加或者减少数字。

 

这个变化可以用来做伪3D效果。比如下面的例子:

Xaml 文件

<TextBlock
  FontFamily="Verdana"
  FontSize="32"
  FontWeight="Bold" 
  Foreground="Black"
  Text="Translated Text">
  <TextBlock.RenderTransform>
    <TranslateTransform X="2" Y="2" />
  </TextBlock.RenderTransform>
</TextBlock>
<TextBlock
  FontFamily="Verdana"
  FontSize="32"
  FontWeight="Bold" 
  Foreground="Coral"
  Text="Translated Text"/>

执行效果:

image

旋转 RotateTransform

旋转是以之前定义的中心点为圆心,进行旋转指定的角度。 正数表示顺时针旋转,负数表示逆时针旋转。

image

上述功能页的“使用相对值”的逻辑跟 TranslateTransform 的逻辑一样。

我们在 image 上拖动鼠标,也可以实现手工旋转。

在输入数字框里面,我们使用滚轮,也可以自动增加或者减少数字。

在 Xaml 中是类似如下的代码:

<RotateTransform Angle="58.884002685546875"/>

注:

RotateTransform  本身具有定义中心点的功能,类似代码如后:<RotateTransform Angle="30" CenterX="1" CenterY="0.8" />

但是,一旦我们定义了元素的 RenderTransformOrigin, 则 RenderTransformOrigin 优先级高于 RotateTransform 定义的中心点。

 

缩放 ScaleTransform

如下图所示,我们可以使用 ScaleTransform 沿水平或垂直方向拉伸或收缩对象。

image

ScaleX 属性指定使对象沿 x 轴拉伸或收缩的量,ScaleY 属性指定使对象沿 y 轴拉伸或收缩的量。

缩放是以之前的中心点为原点进行的缩放。可以为负值,表示到了中心点的左边(ScaleX 为负),上面(ScaleY 为负)。

在Xaml中代码类似如下:

<ScaleTransform ScaleX="-0.95" ScaleY="1.05"/>

缩放常用于选中某个对象时突出显示。

注:

ScaleTransform 本身具有定义中心点的功能,类似代码如后:<ScaleTransform ScaleY="2" CenterX="0.8" CenterY="1"/>

但是,一旦我们定义了元素的 RenderTransformOrigin, 则 RenderTransformOrigin 优先级高于 ScaleTransform 定义的中心点。

 

倾斜 SkewTransform

以之前定义的中心点为原点,进行倾斜。

image

默认是不倾斜的,即都是0。

可以为正数,也可以为负数。数字表示以中心点为中心倾斜的度数。

在Xaml中代码类似如下:

<SkewTransform AngleX="30" AngleY="-1"/>

注:

SkewTransform 本身具有定义中心点的功能,类似代码如后:<SkewTransform AngleX="26" AngleY="0" CenterX="0.8" CenterY="1.0"/>

但是,一旦我们定义了元素的 RenderTransformOrigin, 则 RenderTransformOrigin 优先级高于 SkewTransform 定义的中心点。

 

翻转

至于Blend 中的“反转”则是上述四种转换的一个汇总使用的几个可能会比较常用的场景。

image

image  X 轴翻转,则它的缩放变化 ScaleTransform 的 ScaleX 再乘以-1。

image X 轴翻转,则它的缩放变化 ScaleTransform 的 ScaleY 再乘以-1。

 

 

参考资料:

Silverlight学习笔记--通用绘图属性
http://blog.joycode.com/ghj/archive/2009/11/30/115793.joy

UIElement.RenderTransformOrigin 属性
http://msdn.microsoft.com/zh-cn/library/system.windows.uielement.rendertransformorigin.aspx

TranslateTransform 类
http://msdn.microsoft.com/zh-cn/library/system.windows.media.translatetransform(VS.95).aspx

RotateTransform 类
http://msdn.microsoft.com/zh-cn/library/system.windows.media.rotatetransform.aspx

ScaleTransform 类
http://msdn.microsoft.com/zh-cn/library/system.windows.media.scaletransform.aspx

SkewTransform 类
http://msdn.microsoft.com/zh-cn/library/system.windows.media.skewtransform(VS.95).aspx

posted on 2010-01-05 16:50:16 by ghj1976  评论(1) 阅读(1781)

 
2010年01月04日

假设我们有一个空白项,对应的Xaml文件为:

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="SilverlightApplication4.MainPage"
	Width="640" Height="480">

	<Grid x:Name="LayoutRoot" Background="White"/>
</UserControl>

我们在其中增加一个 Border 控件,并用 钢笔或者铅笔画一个不规则图形。

image

这时候,产生的Xaml 文件类似如下:

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="SilverlightApplication4.MainPage"
	Width="640" Height="480">

	<Grid x:Name="LayoutRoot" Background="White">
		<Border Height="115" Margin="103,47,102,0" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="1">
			<Path Fill="White" Stretch="Fill" Stroke="Black" Margin="73.5,35.598,149.5,12.5" UseLayoutRounding="False" 
Data="M83,46 C228,18 284,65 284,65 L217,100.99988 L177,79.999947 L141,93.999901 L75,76.999962 z"/> </Border> </Grid> </UserControl>

然后我们在“对象和时间线中”选择我们要用的Path 对象,如下图:

image

点击 路径 --》 生成剪切路径

在出现的 生成剪切路径选择窗口中,我们选择需要使用这个路径的对象,这里我们选择“Border” 对象

image

点击确定后,我们就可以获得一个不规则的 Border, 这时候的Xaml 文件为:

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="SilverlightApplication4.MainPage"
	Width="640" Height="480">

	<Grid x:Name="LayoutRoot" Background="White">
		<Border Height="115" Margin="103,47,102,0" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="1" 
Clip="M83,45.999935 C228,17.999838 284,65 284,65 L217,101 L177,80 L141,94 L75,77 z"/> </Grid> </UserControl>

适当调整颜色后,看到的Border 就是如下图:

image

其他控件我们想要设计成不规则方式, 在Blend 中的设计步骤类似。

参考资料:

请教怎样用path做一个不规则的border
http://topic.csdn.net/u/20091216/15/9585d9b5-5fb9-4fe0-bb24-5cd9f5a1b46c.html

posted on 2010-01-04 17:32:05 by ghj1976  评论(0) 阅读(1779)

 

Border 控件用于在另一元素周围绘制边框或背景。

先看一个简单的例子

Xaml 文件

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="SilverlightApplication2.MainPage"
	Width="300" Height="150">
  	<Border Background="Coral" Width="250" Margin="12" 
	Padding="10" CornerRadius="30,38,150,26"
	BorderThickness="8 15 10 2" BorderBrush="Aqua">
    	<TextBlock FontSize="12">Text Surrounded by a Border</TextBlock>
	</Border>
</UserControl>

演示效果图:

image

其中属性说明:

Border.Padding 属性  获取或设置边框与其子对象之间的距离。

FrameworkElement.Margin 属性 获取或设置 FrameworkElement 的外边距。

Border.CornerRadius 属性 获取或设置边框的角的半径。 上面例子中是按照 topLeft,topRight,bottomRight,bottomLeft 的顺序来设置的。

Border.BorderThickness 属性 获取或设置边框的粗细。默认情况下,四个边的粗细都为 0。 上面例子中是按照 left,top,right,bottom 顺序来设置的:

在如上所示的 XAML 语法中,可以使用空格而不是逗号作为值之间的分隔符。 
Border.BorderBrush 属性 获取或设置用于创建边框的 Brush。
需要注意的是: 

Border 只能包含一个子对象。如果要在多个对象周围放置一个边框,应将这些对象包装到一个容器对象中,例如 StackPanel。

下面的示例就演示了一个如何在 StackPanel 中包含的多个 TextBlock 对象,并在周围放置一个边框。

<Border BorderThickness="5" BorderBrush="Blue" >
    <StackPanel Grid.Column="0" Grid.Row="0">
        <TextBlock Text="One"/>
        <TextBlock Text="Two"/>
        <TextBlock Text="Three"/>
    </StackPanel>
</Border>

我们如果修改其他控件的 ControlTemplate 时,我们就会看到, Border 控件在很多地方都用到了,用于模拟选中的3D效果。这个逻辑的实现很简单,通过修改 Opacity 来实现,下面就是一个简化版的演示,当用户点击文本时,出现一个文本的边框。

Xaml 代码

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="SilverlightApplication2.MainPage"
	Width="300" Height="150">
 <Grid x:Name="LayoutRoot" >
    <Border x:Name="TextBorder" BorderThickness="10" >
    	<Border.BorderBrush>
        	<SolidColorBrush Color="Red" Opacity="0" />
        </Border.BorderBrush>
        <TextBlock MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" Text="Hello" />
    </Border>  
</Grid>
</UserControl>

C# 代码

private void TextBlock_MouseLeftButtonDown(object sender,
	System.Windows.Input.MouseButtonEventArgs e)
{
	TextBorder.BorderBrush.Opacity = 1;
}

 

参考资料:

Using the Border control in Silverlight 2
http://www.silverlightshow.net/items/Using-the-Border-control-in-Silverlight-2-Beta-1-.aspx

Border 类
http://msdn.microsoft.com/zh-cn/library/system.windows.controls.border(VS.95).aspx

稳扎稳打Silverlight(3) - 2.0控件之Border, Button, Calendar, Canvas, CheckBox, ComboBox
http://www.cnblogs.com/webabcd/archive/2008/10/09/1307493.html

Show/Hide a Border and other Border fun
http://blogs.msdn.com/silverlight_sdk/archive/2008/07/30/show-hide-a-border-and-other-border-fun.aspx

Silverlight里的Rectangle与border有啥区别呀?
http://social.microsoft.com/Forums/zh-CN/silverlightzhchs/thread/86581cff-f660-414f-94dc-f4e77a02090a

Silverlight Border Control
http://www.c-sharpcorner.com/UploadFile/raj1979/SilverlightBorder10162008030241AM/SilverlightBorder.aspx

border控件中的一些疑问
http://bbs.blueidea.com/viewthread.php?tid=2957515

posted on 2010-01-04 15:22:53 by ghj1976  评论(3) 阅读(1784)

 
2009年12月30日

WPF 和 Silverlight 支持 Style 机制,它允许我们把控件的属性值封装成可重用的资源。我们可以把这些样式声明保存在独立于页面的其他文件中(当然本文件也可以),然后就可以在一个应用程序中跨控件和页面重用(甚至跨多个应用程序重用)。在做一些基本定制的场景下,概念上类似于在 HTML 中重用 CSS。

 

一个样式的简单例子

我们给一个园定义一个名叫 EllipseStyle1 的样式,然后应用这个样式。

Xaml 文件

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="SilverlightApplication_Style.MainPage"
	Width="300" Height="300">
	<UserControl.Resources>
		<Style x:Key="EllipseStyle1" TargetType="Ellipse">
			<Setter Property="Fill">
				<Setter.Value>
					<LinearGradientBrush EndPoint="0.9,1" StartPoint="0.1,0.1">
						<GradientStop Color="#FF42B34A" Offset="0"/>
						<GradientStop Color="#FFC03535" Offset="1"/>
					</LinearGradientBrush>
				</Setter.Value>
			</Setter>
			<Setter Property="Margin" Value="10,0,0,0"/>
			<Setter Property="Cursor" Value="Hand"/>
			<Setter Property="StrokeThickness" Value="20"/>
			<Setter Property="VerticalAlignment" Value="Center"/>
			<Setter Property="HorizontalAlignment" Value="Center"/>
		</Style>
	</UserControl.Resources>

	<Grid x:Name="LayoutRoot" Background="White">
		<Ellipse Height="100" Width="100" Style="{StaticResource EllipseStyle1}" />
	</Grid>
</UserControl>

效果图:

image

这里简单期间把样式跟控件放在一个文件中了, 实际我们还可以放在另外一个文件。

使用 Blend 设计样式时,我们会看得更清楚,

使用菜单在 对象 –> 编辑样式 –> 创建空项 打开创建 Style 资源时,我们就可以看到我们可以在多个地方保存样式:

image

之后在 Blend 中编辑时,可以在资源中选择对应的样式名字,然后如下图所示进行编辑:

编辑可以在属性窗口修改任何想修改的内容。

image

在编辑完毕后,在对象和时间线中,点击 image 按钮就可以回到正常状态。

image

参考资料:

Silverlight教程第四部分:使用 Style 元素更好地封装观感
http://blog.joycode.com/scottgu/archive/2008/02/29/114915.joy

一步一步学Silverlight 2系列(8):使用样式封装控件观感
http://www.cnblogs.com/Terrylee/archive/2008/03/08/Silverlight2-step-by-step-part8-styles.html

解说:Silverlight Style,Setter(XAML/Design)换肤机制
http://blog.csdn.net/bobby96333/archive/2008/10/22/3126363.aspx

Silverlight2 边学边练 之六 设定风格
http://www.cnblogs.com/gnielee/archive/2009/08/02/1537122.html

Silverlight 2 : 关于ListBox的一个Layout Bug及其解决方法
http://www.cnblogs.com/sun/archive/2009/03/04/1402648.html

Silverlight项目中"自定义控件开发/Style"学习笔记
http://www.cnblogs.com/yjmyzz/archive/2009/11/11/1600791.html

Quick Silverlight Tip: Define control style dynamically
http://blogs.microsoft.co.il/blogs/alex_golesh/archive/2008/09/09/quick-silverlight-tip-define-control-style-dynamically.aspx

posted on 2009-12-30 17:16:40 by ghj1976  评论(1) 阅读(1991)

 

SQL Server 的 ltrim 和 rtrim 函数只会取消 char(32) 的字符, char(9) 之类的字符则不会剔除。今天在处理论坛的一个bug时,发现数据多了空格,就是char(9)在作怪。

一个演示SQL代码:

declare @s nvarchar(50)
select @s = char(32)+char(9)+'*'
print('%'+@s+'%')
select @s = ltrim(rtrim(@s))
print('%'+@s+'%')
print (str(len(@s)))

而 C# 中则没有类似问题,它剔除了很多非 char(32) 的空格。

演示代码:

static void Main(string[] args)
{
    string s = string.Format("{0}{1}*", (char)32, (char)9);
    Console.WriteLine("%" + s + "%");
    Console.WriteLine(s.Length);
    s = s.Trim();
    Console.WriteLine("%" + s + "%");
    Console.WriteLine(s.Length);
    Console.ReadLine();
}

MSDN上一些空格的资料:

下表列出了被 Trim 方法移除的空白字符。第一列列出了字符的 Unicode 名称,第二列列出了标识该字符的 Unicode 码位的十六进制表示法。
(请注意,尽管传递特定字符时静态 Char.IsWhiteSpace(Char) 方法返回了 true,但该字符不一定被 Trim 方法移除。(作者注:MSDN上这句话很让我困惑,下面2个表中,Char.IsWhiteSpace中的空格都出现在Trim 中的空格了呀?))

Unicode 名称 Unicode 码位
CHARACTER TABULATION U+0009
LINE FEED U+000A
LINE TABULATION U+000B
FORM FEED U+000C
CARRIAGE RETURN U+000D
SPACE U+0020
NEXT LINE U+0085
NO-BREAK SPACE U+00A0
OGHAM SPACE MARK U+1680
EN QUAD U+2000
EM QUAD U+2001
EN SPACE U+2002
EM SPACE U+2003
THREE-PER-EM SPACE U+2004
FOUR-PER-EM SPACE U+2005
SIX-PER-EM SPACE U+2006
FIGURE SPACE U+2007
PUNCTUATION SPACE U+2008
THIN SPACE U+2009
HAIR SPACE U+200A
ZERO WIDTH SPACE U+200B
LINE SEPARATOR U+2028
PARAGRAPH SEPARATOR U+2029
IDEOGRAPHIC SPACE U+3000
ZERO WIDTH NO-BREAK SPACE U+FEFF

会被 Char.IsWhiteSpace( 认为是空白字符的包括以下Unicode 字符:

  • SpaceSeparator 类别的成员,该类别包括 SPACE 字符 (U+0020)。
  • LineSeparator 类别的成员,该类别只包括 LINE SEPARATOR 字符 (U+2028)。
  • ParagraphSeparator 类别的成员,该类别只包括 PARAGRAPH SEPARATOR 字符 (U+2029)。
  • 字符 CHARACTER TABULATION (U+0009)、LINE FEED (U+000A)、LINE TABULATION (U+000B)、FORM FEED (U+000C)、CARRIAGE RETURN (U+000D)、NEXT LINE (U+0085) 和 NO-BREAK SPACE (U+0000A0)。

posted on 2009-12-30 14:29:51 by ghj1976  评论(0) 阅读(1917)

 

我们以前要实现朗读一段文本,需要如何做呢?

首先在项目中引用 Microsoft Speech Object Library 。 如下Com组件:

image

然后是一堆复杂的代码。这部分的实现可以采看以下几篇文章:

.Net平台下开发中文语音应用程序
http://www.microsoft.com/china/community/program/originalarticles/TechDoc/Cnspeech.mspx

C#中实现语音朗读(短信 & 语音短信)sms
http://www.cnblogs.com/joyyuan97/archive/2009/02/26/1398716.html

 

当然 由于 .Net Framework 3.0 中增加了一个命名空间:System.Speech。 实际上从 .Net Framework 3.0 开始,我们要实现语音朗读要简单多了,具体如何实现可以参看我之前的博客:用.net 编码实现朗读文本的方法。 但是我们操作其他微软没有封装的 Com 组件,仍然跟之前一样超级复杂,而且需要相当的技巧。

 

在 .Net 4.0 中,我们只需要三行代码就可以实现上面的功能,而且项目不需要引用 Microsoft Speech Object Library 。超简单,这是利用了 C# 4.0 的动态查找新特性, 即 dynamic 类型。有关 dynamic 的基础知识,请参看我前篇博客: C# 4.0 特性: dynamic 和 ExpandoObject

C# 4.0 的项目不需要引用任何其他组件,只需要下面简单的几行代码,完成阅读文字的功能。

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Type type = Type.GetTypeFromProgID("SAPI.SpVoice");
            dynamic spVoice = Activator.CreateInstance(type);
            spVoice.Speak("你好,郭红俊,欢迎使用 CSharp 4.0!");            
        }
    }
}


这个例子引用了 Speech API 中的 SAPI.SpVoice 对象,并调用了其 Speak() 方法。

Type.GetTypeFromProgID 用于获取与指定程序标识符 (ProgID) 关联的类型。

ProgID 是程序员给某个CLSID指定一个易记的名字。在注册表的 HKey_Classes_Root 下,有版本号的ProgID和无版本号的ProgID都会列出,一般无版本号的除了有CLSID子键外会还有CurVer子键来标明版本。

Type.GetTypeFromProgID  是 .NET Framework 1.0 就具有的功能, 但为何到了 .NET Framework 4.0 我们才可以写出这么简单的代码, 这关键就是 dynamic 类型的引用。

任何直接声明为 dynamic 类型的变量,或者从函数中返回 dynamic 类型的值,都将自动地视为后期绑定。即在运行时才会被初始化绑定。 由于这个原因,我们才会用这么简单的代码实现对Com的调用。 

 

参考资料:

C# 4.0 特性: dynamic 和 ExpandoObject
http://blog.joycode.com/ghj/archive/2009/12/29/115832.joy

ProgID是什么
http://kb.cnblogs.com/a/1218548/

posted on 2009-12-30 10:58:22 by ghj1976  评论(1) 阅读(2034)

 
2009年12月29日

C# 4.0引入了一个新类型:dynamic,简单来说,任何直接声明为这种类型的变量,或者从函数中返回这种类型的值,都将自动地视为后期绑定。即在运行时才会被初始化绑定。这类似于在Visual Basic中把变量声明为“object”,不过它现在可以支持任何类型系统了,不仅仅是CTS(通用类型规范)和COM。

C# 4.0 的主打特性就是动态类型。也就在这里体现。

在 New features in CSharp 4.docx 中提到 dymanic主要应用于下面的场景也是这样:

  • 自动反射
  • COM组件互操作
  • 混合编程,例如IronRuby和IronPython
  • 处理Html DOM对象

一个简单例子:

static void Main(string[] args)
{
    dynamic person = new System.Dynamic.ExpandoObject();
    person.Name = "cary";
    person.Age = 25;
    person.ShowDescription = new Func<string>(() => person.Name + person.Age);
    
    Console.WriteLine(person.Name + person.Age + person.ShowDescription());
    Console.ReadLine();
}

这里的 System.Dynamic.ExpandoObject 是个特殊的对象,简单地说它的行为可以被“扩展”——是如动态语言般真正的扩展,而非静态的多态。当我们使用dynamic 饰变量后,在它之上的方法调用会由编译器和DLR配合出不一样的行为。例如,我们在调用一个方法的时候,DLR会先检查这个动态对象上是否存在符合这个签名的方法,存在则最好,否则便会调用TryInvokeMember来“执行”一个动态方法,而它的参数便是此次调用的全部信息。这样的做法被称为“Method Missing”操作。

DLR 和 CLR 以及编程语言的关系看下图:

image_thumb_2

 

注意点:

使用 Dynamic 将导致只能在运行时才能被测试。这就是为什么当你用dynamic类型时,单元测试在你的代码中变得很重要,很重要!!

 

参考资料:

C#4.0新特性:可选参数,命名参数,Dynamic
http://www.cnblogs.com/carysun/archive/2009/12/09/CSharp4.html

翻译:Visual C# 4.0的新特性-第三部分-Dynamic ExpendoObject
http://www.cnblogs.com/codeyu/archive/2009/12/08/1616839.html

C# 4.0中dynamic的用法
http://space.itpub.net/740297/viewspace-600670

介绍C# 4.0新特性dynamic
http://developer.51cto.com/art/200908/144976.htm

二十行C#代码打造Ruby Markup Builder
http://www.cnblogs.com/JeffreyZhao/archive/2009/10/27/implement-ruby-markup-builder-in-20-lines-of-c-sharp-codes.html

Dynamic in C# 4.0: Introducing the ExpandoObject
http://blogs.msdn.com/csharpfaq/archive/2009/10/01/dynamic-in-c-4-0-introducing-the-expandoobject.aspx

C#4.0的dynamic用法(一)——巧用反射
http://www.cnblogs.com/architect/archive/2009/03/13/1410921.html

C#动静结合编程之三:Duck Typing
http://www.cnblogs.com/weidagang2046/archive/2009/03/26/1421943.html

也谈.NET反射的封装
http://www.cnblogs.com/weidagang2046/archive/2009/04/30/1446928.html

C#动态特性的更多消息
http://www.infoq.com/cn/news/2009/04/Dynamic-CSharp

Fun With Method Missing and C# 4
http://haacked.com/archive/2009/08/26/method-missing-csharp-4.aspx

posted on 2009-12-29 17:03:16 by ghj1976  评论(2) 阅读(2216)

 
2009年12月28日

我们先来看一段超简单的使用了这个特性的代码例子:

public static void ShowMessage(string msg = "")
{
    Console.WriteLine("Hello {0}", msg);
}

static void Main(string[] args)
{
    // 使用默认的 msg = ""
    ShowMessage();

    // 使用指定的参数值
    ShowMessage("ghj1976");

    // 指定参数值的又一种写法
    ShowMessage(msg: "郭红俊");

    Console.ReadLine();
}

为什么需要开放命名参数和可选参数呢?

  • 这是出于动态语言运行时兼容性的要求。动态语言中存在动态绑定的参数列表,有时候并不是所有的参数值都需要指定(有些语言可能没有重载决策);
  • 另外,在一些 COM 互操作时,往往 COM Invoke 的方法参数列表非常的长(例如 ExcelApplication.Save,可能需要 12 个参数),但 COM 暴露的参数的实际值往往为 null,只有很少一部分参数需要指定植,如 ExcelApplication.Save(),可能不需要指定任何参数值,或者仅仅一个值,例如 fileType。为了精简书写的代码,就有着这个特性。

 

一些注意点:

上面 ShowMessage 函数写法的可选参数(Optional Parameters)必须放在最后,否则将引发 "Optional parameters must appear after all required parameters" 编译错误。

比如这样的写法就是不允许的:

private static void Test2(int x = 0x7b, double y = 45.3, string w)
{
    Console.WriteLine("{0},{1},{2}", s, x, y);
}

但是换种写法就可以了:

如下:

        private static void Test(
  [System.Runtime.InteropServices.Optional, System.Runtime.InteropServices.DefaultParameterValue(0x7b)] int x,
  [System.Runtime.InteropServices.Optional, System.Runtime.InteropServices.DefaultParameterValue(45.3)] double y,
            string s
        )
        {
            Console.WriteLine("{0},{1},{2}", s, x, y);
        }

最初的这种写法在编译时,就是编译生成了 System.Runtime.InteropServices.Optional, System.Runtime.InteropServices.DefaultParameterValue 这样的参数属性。
Optional Parameters 的实质就是:
编译器为可选参数增加了 OptionalAttribute 和 DefaultParameterValueAttribute 特性,以便于引用编译和反射调用时能获取默认值。
至于不用 OptionalAttribute 和 DefaultParameterValueAttribute 特性的写法只不过是种语法糖而已。

 

当你的方法有多个同一类型的可选参数(optional parameters)时,命名参数(Named parameters)特别有用。如果不用命名参数,编译器就不知道传递的是哪个参数。

仍然是上面的 private static void Test 函数,我们调用时, 就必须这么写:

Test(s: "蝈蝈俊.net");

否则如果我们写成 Test("蝈蝈俊.net"); 就会报错误: No overload for method 'Test' takes 1 arguments

Named Parameters 的实质就是:
命名参数,无非是变相告知参数键值而已,最终编译结果还是按照原有的规则和顺序生成方法调用。这只不过是中语法糖而已。

 

 

参考资料:

C# 4.0 新特性 -- 命名参数和可选参数
http://blog.csdn.net/hustorochi/archive/2009/03/20/4007260.aspx

C#特性聚焦:可选和命名参数、COM互操作性
http://www.infoq.com/cn/news/2008/11/CSharp-Optional

C#4.0新特性:可选参数,命名参数,Dynamic
http://www.cnblogs.com/carysun/archive/2009/12/09/CSharp4.html

C# 4.0 - Named and Optional Parameters - Behind the Scenes
http://codebetter.com/blogs/matthew.podwysocki/archive/2008/10/29/c-4-0-named-and-optional-parameters-behind-the-scenes.aspx

[C# 4.0] 4. Named & Optional Parameters
http://www.rainsts.net/article.asp?id=879

C# 4.0 Optional Parameters 和Named Parameters
http://blog.csdn.net/shanyou/archive/2009/10/27/4735970.aspx

posted on 2009-12-28 17:15:30 by ghj1976  评论(4) 阅读(2201)

 

Silverlight数据绑定有三种模式(没有WPF的 OneWayToSource 模式),如下:

  • OneTime:一次绑定,在绑定创建时使用源数据更新目标,适用于只显示数据而不进行数据的更新。 这是绑定的默认情况。
  • OneWay:单向绑定,在绑定创建时或者源数据发生变化时更新到目标,适用于显示变化的数据。
  • TwoWay:双向绑定,在任何时候都可以同时更新源数据和目标。

下面是这三种的代码演示:

OneTime 绑定

这种数据绑定模式,只是显示数据而不对数据做任何修改,默认的绑定模式就是OneTime绑定。

绑定到一个实体的一个属性:

Xaml 文件

<TextBlock x:Name="tb_1" Text="{Binding I}"  Margin="100,50,100,200" />

或者可以稍稍复杂的写法:

<TextBlock x:Name="tb_1" Text="{Binding Path=I}"  Margin="100,50,100,200" />

 

CS 代码文件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightApplication_Binding
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            BindingDemoObject o = new BindingDemoObject();
            o.I = 15;
            tb_1.DataContext = o;
        }
    }

    public class BindingDemoObject
    {
        public int I {get;set;}
    }
}

如果要绑定到一个实体,则演示代码如下:

<TextBlock x:Name="tb_1" Text="{Binding}"  Margin="100,50,100,200" />
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    int w = 30;
    tb_1.DataContext = w;
    // 当然也可以写成:
    // tb_1.DataContext = 30;
}

OneWay 绑定

如果需要在数据源发生变化时能够通知UI进行相应的更新,则需要使用单向绑定OneWay或者双向绑定TwoWay。

若要支持 OneWay 或 TwoWay 绑定,从而使绑定目标属性能够自动反映绑定源的动态更改(例如,用户编辑窗体后,预览窗格会自动更新),类需要提供相应的属性更改通知。即创建实现 INotifyPropertyChanged 的类。

下面要演示的例子是当点击按钮时,实体的一个属性发生变化,继而前台显示也发生变化。

Xaml 文件

<Grid x:Name="LayoutRoot" Background="White">
        <TextBlock x:Name="tb_1" Text="{Binding I, Mode=OneWay}"  Margin="100,50,100,200" />
        <Button Content="变化"   Margin="222,112,0,0" Name="button1" Width="75" Click="button1_Click" />
</Grid>

CS 代码文件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;


namespace SilverlightApplication_Binding
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        BindingDemoObject o = new BindingDemoObject();

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            o.I = 15;
            tb_1.DataContext = o;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            o.I = 58;
        }
    }

    public class BindingDemoObject : System.ComponentModel.INotifyPropertyChanged
    {
        private int _i = 0;

        public int I
        {
            get
            {
                return _i;
            }
            set
            {
                _i = value;
                OnPropertyChanged("I");
            }
        }

        /// <summary>
        /// Declare the event
        /// </summary>
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Create the OnPropertyChanged method to raise the event
        /// </summary>
        /// <param name="name"></param>
        protected void OnPropertyChanged(string name)
        {
            System.ComponentModel.PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new System.ComponentModel.PropertyChangedEventArgs(name));
            }
        }

    }
}

 

TwoWay 绑定

网上很多例子没有 Twoway的演示,下面就是一个 Twoway的演示。

Xaml 文件

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	x:Class="SilverlightApplication_TwoWayBinding.MainPage"
	Width="400" Height="200" mc:Ignorable="d">
	<Grid x:Name="LayoutRoot" Background="White">
		<Ellipse Fill="#FF2F70C0" Stroke="Black" Height="57" HorizontalAlignment="Left" Margin="52,28,0,0" VerticalAlignment="Top" Width="{Binding Value, ElementName=silderSelf, Mode=OneWay}" />
		<Slider x:Name="silderSelf" Height="30" Margin="52,103,48,0" VerticalAlignment="Top" Maximum="300" Minimum="10" LargeChange="10" SmallChange="1" Value="100" Width="300"/>
		<TextBox Height="30" HorizontalAlignment="Left" Margin="52,150,0,0" VerticalAlignment="Top" Width="150" Text="{Binding Value, ElementName=silderSelf, Mode=TwoWay}" TextWrapping="Wrap"/>
	</Grid>
</UserControl>

演示效果:

 

解释: 

这里我们把椭圆的宽度和 TextBox 的值捆绑到 Slider 的值。
对椭圆的捆绑是 OneWay 模式, 表示只是读取Slider 的值。

TextBox  的捆绑则是 TwoWay, 表示我们即可以接受 Slider 的值,也可以设置 Slider 的值。 当 TextBox  中输入了值,按 Tab 离开焦点后,我们就可以看到 Slider 和 椭圆的值都发生变化了。

当我们移动 Slider 时, TextBox   的值和 椭圆的宽度都发生变化。

 

 

参考资料:

一步一步学Silverlight 2系列(11):数据绑定
http://www.cnblogs.com/Terrylee/archive/2008/03/08/Silverlight2-step-by-step-part11-Data-Binding.html

如何在Blend设置数据绑定
http://msdn.microsoft.com/zh-cn/library/cc295161(Expression.30).aspx

silverlight数据绑定模式TwoWay,OneWay,OneTime的研究
http://www.cnblogs.com/yjmyzz/archive/2009/11/09/1599058.html

posted on 2009-12-28 11:15:32 by ghj1976  评论(0) 阅读(1859)

 
2009年12月24日

OAuth 协议是现在众多网站提供API服务所选择的认证方式,是由Blaine Cook、Chris Messina、Larry Halff 及David Recordon共同发起,目的是为API服务提供一个安全、统一和开放的标准。

官方网站对 OAuth 的一句话介绍是:

   An open protocol to allow secure API authentication in a simple and standard method from desktop and web applications.

大概意思是说 OAuth 是一种开放的协议,为桌面程序或者基于BS的web应用提供了一种简单的标准的方式去访问需要用户授权的API服务。OAUTH认证授权具有以下特点:

1. 简单:不管是 OAuth 服务提供者还是应用开发者,都很容易于理解与使用;

2. 安全:没有涉及到用户密钥等信息,更安全更灵活;

3. 开放:任何服务提供商都可以实现 OAuth ,任何软件开发商都可以使用 OAuth

OAUTH认证授权流程:

下面这个图就是演示了认证流程。这个图来自: http://wiki.opensocial.org/index.php?title=OAuth_Use_Cases 

Oauth_3legged

Oauth_legend

上述5个步骤解释如下:

  1. A user wishes to use their social network data inside of a third party website or application. The application server contacts the social network, but does not have the user's account information, and does not have permission to access the user's data.
    用户希望在第三网站和应用上使用他在SNS网站上的用户信息,这些第三方网站联系SNS网站,但是由于没有用户认证信息,这时这些用户信息是不允许访问的。
    更技术点说法:
    第三方应用程序向SNS网站授权服务发出获取request token的请求。
  2. The social network responds with information that the application server uses to redirect the user's web browser to a special login page on the social network's domain.
    SNS网站把用户的浏览器重定向到SNS网站的登录页面。
    更技术点说法:
    SNS授权服务响应请求,返回一个尚未认证的request token。
    第三方应用获取响应中包含的request token,按照协议规范,附带这个request token,将其重定向到SNS提供的授权页面(User Authorization URL)。
  3. If the user is logged out of the social network, they input their username and password as if they were normally logging into the site. After they log in, or if they were already logged in (with a cookie), they are asked by the social network to share data with the application.
    如果用户没有登录,用户向普通登录一样,输入用户名和密码完成登录。如果用户已经登录(使用记录Cookie的方式),会出现一个页面,问用户是否允许共享他的SNS信息给第三方网站。
    更技术点说法:
    在Google提供的授权页面上,用户按照提示输入用户账号信息。

  4. Once permission has been granted, the social network redirects the user's web browser to a predefined URL on the application server, along with a token that can be used to access the user's information.
    一旦用户选择信任第三方网站,SNS网站将把Web浏览器重定向到第三方网站,同时把SNS的用户信息传递过去。
    更技术点说法:
    用户决定允许或拒绝授权给第三方应用,如果用户拒绝授权给此第三方应用,则被重定向到SNS的页面,而不会再回到第三方应用的页面上。
    如果用户授权给第三方应用,那么,SNS授权服务接收此请求,将用户重定向到第三方应用提供的页面上,并传递被认证了的request token。
  5. Using the token as described in the OAuth specification, the application server is now able to access the user's data on the social network.
    这样第三方网站就可以访问SNS网站的用户信息了。
    更技术点说法:
    第三方应用接收到认证的request token后,再次向SNS账号服务发起一次HTTP请求,以换取access token。
    SNS 账户授权服务接收请求,验证是否合法。如果合法,则返回一个access token。


从上面的步骤可以看出,用户始终没有将其用户名与密码等信息提供给使用者(第三方软件),从而更安全。

 

OAUTH相关术语

明白了流程,再看技术术语就会简单很多。在上面流程中,在更技术说法中提到了一些术语,这些OAuth的术语解释如下:

OAUTH相关的三个URL

  • Request Token URL: 获取未授权的Request Token服务地址;
  • User Authorization URL: 获取用户授权的Request Token服务地址;
  • Access Token URL: 用授权的Request Token换取Access Token的服务地址;

OAUTH相关的参数定义:

  • oauth_consumer_key: 使用者的ID,OAUTH服务的直接使用者是开发者开发出来的应用。所以该参数值的获取一般是要去OAUTH服务提供商处注册一个应用,再获取该应用的oauth_consumer_key。如Yahoo该值的注册地址为:https://developer.yahoo.com/dashboard/
  • oauth_consumer_secret:oauth_consumer_key对应的密钥。
  • oauth_signature_method: 请求串的签名方法,应用每次向OAUTH三个服务地址发送请求时,必须对请求进行签名。签名的方法有:HMAC-SHA1、RSA-SHA1与PLAINTEXT等三种。
  • oauth_signature: 用上面的签名方法对请求的签名。
  • oauth_timestamp: 发起请求的时间戳,其值是距1970 00:00:00 GMT的秒数,必须是大于0的整数。本次请求的时间戳必须大于或者等于上次的时间戳。
  • oauth_nonce: 随机生成的字符串,用于防止请求的重放,防止外界的非法攻击。
  • oauth_version: OAUTH的版本号,可选,其值必须为1.0。

OAUTH HTTP响应代码:

  • HTTP 400 Bad Request 请求错误
    • Unsupported parameter 参数错误
    • Unsupported signature method 签名方法错误
    • Missing required parameter 参数丢失
    • Duplicated OAuth Protocol Parameter 参数重复

 

  • HTTP 401 Unauthorized 未授权
    • Invalid Consumer Key 非法key
    • Invalid / expired Token 失效或者非法的token
    • Invalid signature 签名非法
    • Invalid / used nonce 非法的nonce

 

参考资料:

OAuth
http://en.wikipedia.org/wiki/OAuth

Developer's Guide: Data API Protocol – OAuth for Web Applications
http://code.google.com/intl/zh-CN/apis/youtube/2.0/developers_guide_protocol_oauth.html

OAUTH协议简介
http://blog.csdn.net/hereweare2009/archive/2009/03/08/3968582.aspx

An OAuth library for .NET consumers and service providers 
http://code.google.com/p/oauth-dot-net/

OAuth不断获得动力
http://www.infoq.com/cn/news/2008/06/oauth_spring

豆瓣 API OAuth认证
http://www.douban.com/service/apidoc/auth

OAuth Use Case
http://wiki.opensocial.org/index.php?title=OAuth_Use_Cases

posted on 2009-12-24 17:08:46 by ghj1976  评论(1) 阅读(2391)

 
2009年12月23日

动画和定时器是紧密相关的,下面的三个例子既可以说是定时器,也可以说是动画。

 

编码使用定时器

编码方式使用定时器,最简单的就是使用 System.Windows.Threading 命名空间的 DispatcherTimer 类。虽然也可以用 System.Timers.Timer,但是实现就会复杂多了,不推荐使用System.Timers.Timer,原因如下:

在每个 Dispatcher (管理线程工作项队列的服务)循环的顶端重新计算 DispatcherTimer。 这样 DispatcherTimer 不能保证会正好在时间间隔发生时执行计时器,但能够保证不会在时间间隔发生之前执行计时器。 这是因为 DispatcherTimer 操作与其他操作一样被放置到 Dispatcher 队列中。 何时执行 DispatcherTimer 操作取决于队列中的其他作业及其优先级。

如果 System.Timers.Timer 用于 WPF/Silverlight 应用程序,则值得注意的是 System.Timers.Timer 运行于不同于用户界面 (UI) 线程的其他线程上。 为了访问用户界面 (UI) 线程上的对象,需要使用 Invoke 或 BeginInvoke 将操作发布到用户界面 (UI) 线程的 Dispatcher 上。

使用 DispatcherTimer 而不是使用 System.Timers.Timer 的原因是 DispatcherTimer 与 Dispatcher(管理线程工作项队列的服务) 运行于相同的线程,并且可以在 DispatcherTimer 上设置 DispatcherPriority。

使用 DispatcherTimer 的例子

XAML 文件

<Grid x:Name="LayoutRoot" Background="White">
  <TextBlock Loaded="StartTimer" x:Name="myTextBlock" />
</Grid>

代码文件

public void StartTimer(object o, RoutedEventArgs sender)
{
    System.Windows.Threading.DispatcherTimer myDispatcherTimer = new System.Windows.Threading.DispatcherTimer();
    myDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 100); // 100 Milliseconds 
    myDispatcherTimer.Tick += new EventHandler(Each_Tick);
    myDispatcherTimer.Start();
}

// A variable to count with.
int i = 0;

// Raised every 100 miliseconds while the DispatcherTimer is active.
public void Each_Tick(object o, EventArgs sender)
{
    myTextBlock.Text = "Count up: " + i++.ToString();
}

 

使用故事版来做的定时器

我们在 Storyboard  的 Completed 事件中再次把Storyboard 起来:  myTimer.Begin();  这就相当于一个定时器。

XAML文件

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="MySilverlight3Study_Animation3.MainPage"
	Width="180" Height="120">
	<UserControl.Resources>
		<Storyboard x:Name="myTimer" Duration="00:00:01"  Completed="myTimer_Completed" />  
 	</UserControl.Resources>
	<Grid x:Name="LayoutRoot" Background="White">
	<Grid.RowDefinitions>
		<RowDefinition/>
		<RowDefinition/>
	</Grid.RowDefinitions>
	
	<Button x:Name="btn" Height="36" Margin="20,5"  Content="开始" Grid.Row="1" 
		Click="Button_Click"/>
	<TextBlock x:Name="txt" Grid.Row="0" Height="40" Width="60" Text="0" 
		TextWrapping="Wrap" Foreground="#FFA72222" FontSize="26.667" 
		FontFamily="Comic Sans MS" FontWeight="Bold" TextAlignment="Center" 
		LineHeight="9.333"/>
	</Grid>
</UserControl>

代码文件

using System;
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;

namespace MySilverlight3Study_Animation3
{
	public partial class MainPage : UserControl
	{
		public MainPage()
		{
			// 为初始化变量所必需
			InitializeComponent();
		}

		private bool isStop = true;
		
		
		private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			if(isStop)
			{
				btn.Content = "暂停";
				myTimer.Begin();
			}
			else
			{
				btn.Content = "继续";
				myTimer.Stop();
			}
			isStop = !isStop;
		}
		
		private int i = 0;   
		
		private void myTimer_Completed(object sender, EventArgs e) 
		{
			i++;
			txt.Text = string.Format("{0}",i);
			myTimer.Begin();
		}
	}
}

 

用 CompositionTarget.Rendering 来做动画和定时器

除了之前提到的几种动画方式,还有一种只能使用代码创建的基于帧的动画方式。需要做的全部工作是响应静态的 CompositionTarget.Rendering 事件,触发该事件是为了为每帧获取内容。这是一种非常低级的方法,除非使用标准的基于属性的动画模型不能满足需要(例如,构建一个简单的游戏、创建一个基于物理的动画,或者构建粒子效果模型(如火焰、雪以及气泡)),否则不会希望使用这种方法。

构建基于帧的动画的基本技术很容易。只需要简单地为静态的CompositionTarget.Rendering事件关联事件处理程序。一旦关联了事件处理程序,Silverlight就会开始不断地调用这个事件处理程序(只要渲染代码执行得足够快,每秒将会调用60次)。

下面是一个简单的演示代码:

using System;
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;

namespace MySilverlight3Study_Animation3
{
	public partial class MainPage : UserControl
	{
		public MainPage()
		{
			// 为初始化变量所必需
			InitializeComponent();
			
			System.Windows.Media.CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);   
		}

		void CompositionTarget_Rendering(object sender, EventArgs e)
                {
			txt.Text = DateTime.Now.ToString();
		}
	}
}

Xaml 文件

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="MySilverlight3Study_Animation3.MainPage"
	Width="180" Height="120">
	<TextBlock x:Name="txt" Text="1" Margin="20" Foreground="Red" TextAlignment="Center" />
</UserControl>

一般游戏,为了性能,都是使用  CompositionTarget.Rendering  事件来做的。而不是之前的2种方式。

 

参考资料:

SilverLight Timers, what to use?
http://advertboy.wordpress.com/2007/08/11/silverlight-timers-what-to-use/

在Silverlight中使用定时器(Timer)
http://blog.csdn.net/SilverlightShanghai/archive/2007/09/02/1768874.aspx

Silverlight 2 手把手(之六) 使用故事版实现定时器
http://blogs.msdn.com/jijia/archive/2008/04/30/silverlight2-timer-storyboard.aspx

Silverlight 2 手把手(之五) 编程实现定时器
http://blogs.msdn.com/jijia/archive/2008/04/29/programming-timer.aspx

How to: Create a Timer
http://msdn.microsoft.com/en-us/library/cc189084(VS.95).aspx

Make a Silverlight Timer (Silverlight 2)
http://blogs.msdn.com/silverlight_sdk/archive/2008/03/27/make-a-silverlight-timer-silverlight-2.aspx

21.4.5 基于帧的动画
http://book.51cto.com/art/200908/145560.htm

Silverlight: How to use CompositionTarget.Rendering event to synchronize discrete and non-discrete animations

http://blogs.msdn.com/marlat/archive/2009/05/24/silverlight-use-compositiontarget-rendering-event-to-synchronize-discrete-and-non-discrete-animations.aspx

CompositionTarget.Rendering事件
http://blog.etvalley.com/index.php/archives/tag/compositiontargetrendering

Silverlight制作逐帧动画 v2 - part1
http://www.cnblogs.com/nasa/archive/2009/09/11/imageBrush-Animate.html

Silverlight制作逐帧动画 v2 - part2
http://www.cnblogs.com/nasa/archive/2009/09/12/imageBrush-Animate-part2.html

Silverlight制作逐帧动画 v2 - part3
http://www.cnblogs.com/nasa/archive/2009/09/13/imageBrush-Animate-part3.html

Blend基础-动画
http://www.cnblogs.com/nasa/archive/2009/11/03/Expression_Blend_Essentials_Animation.html

posted on 2009-12-23 17:12:24 by ghj1976  评论(0) 阅读(1827)

 

System.Data.SqlClient 命名空间下有个类: SqlConnectionStringBuilder  ,可以帮助我们维护链接字符串。 这个类对我们下面的需求场景很有帮助。

对于同一个数据库,我们可能有正常和比较耗时的统计工作两种需求,为何互相不干扰,我们一般可以配置2个数据库链接字符串,类似如下的配置:

Persist Security Info=False;Integrated Security=true;Initial Catalog=Northwind;server=(local);
Persist Security Info=False;Integrated Security=true;Initial Catalog=Northwind;server=(local);Connect Timeout=0;

注: 在没有设置 Connect Timeout 时, Connect Timeout 默认为15秒,如果 Connect Timeout 设置为0,则表示永远不超时。这个设置是以秒为单位的。

其实我们完全可以只配置一个数据库链接字符串,然后使用 SqlConnectionStringBuilder 类来帮助我们实现不同 Connect Timeout 的需求。

演示代码如下:

 

// connString 原汁原味的配置的链接字符串
SqlConnectionStringBuilder connStr = new SqlConnectionStringBuilder(connString);

// 不论之前是否设置了Connect Timeout,这里都强制设置为用不超时
connStr.ConnectTimeout = 0;

// 使用新组合后的链接字符串
SqlConnection conn = new SqlConnection(connStr.ConnectionString);

 

参考资料:

SqlConnectionStringBuilder 类
http://msdn.microsoft.com/zh-cn/library/system.data.sqlclient.sqlconnectionstringbuilder(VS.80).aspx

posted on 2009-12-23 10:23:14 by ghj1976  评论(241) 阅读(2514)

 
2009年12月22日

按照动画的形成方式,Silverlight 动画可以分为两种:

  • 渐变风格方式(也可以叫From/To/By 动画)(确定开始和结束,然后按照一个固定的频率完成渐变) ;
  • 关键帧生成方式 (设定若干中间帧,可以按照指定的节奏来变化,节奏可以忽快忽慢);

渐变式动画的讲解请看博客: Silverlight学习笔记--动画效果-- 渐变风格方式动画 本文介绍关键帧动画:

与渐变(From/To/By )动画类似,关键帧动画以动画形式显示了目标属性的值。它通过定义其持续时间(Duration属性)创建其目标值之间的过渡。但是,与From/To/By 动画创建两个值之间的过渡不同,单个关键帧动画可以创建任意数量的目标值之间的过渡。

与 From/To/By 动画不同,关键帧动画没有设置其目标值所需的 From、To 或 By 属性。而是使用关键帧对象描述关键帧动画的目标值。若要指定动画的目标值,需要创建关键帧对象并将其添加到动画的 KeyFrames 属性。动画运行时,将在您指定的帧之间过渡。

 

几种关键帧动画的动画过度方法(Interpolation Methods)

关键帧动画从一帧到另外一帧,是如何过度的,这个过度策略就是 Interpolation Methods ,MSDN上的翻译竟然叫“内插方法”,我晕,翻译真垃圾。这个过度策略有三种方式:线性(linear interpolation 线性内插)、离散(Discrete Interpolation  离散内插)和样条(Splined Interpolation 样条内插)。

 

linear interpolation 线性

使用线性过度,指定时间段内,动画的播放速度将是固定的。比如,如果关键帧段在 5 秒内, 从 0 过渡到 10,则该动画会在指定的时间产生如下表所示的值。

时间 输出值
0 0
1 2
2 4
3 6
4 8
4.25 8.5
4.5 9
5 10

Discrete Interpolation  离散

使用离散过度,动画函数将从一个值跳到下一个没有内插的值。如果关键帧段在 5 秒内从 0 过渡到 10,则该动画会在指定的时间产生如下表所示的值。动画在持续期间恰好结束之前不会更改其输出值,一直到到了时间点,才会修改。

时间 输出值
0 0
1 0
2 0
3 0
4 0
4.25 0
4.5 0
5 10

Splined Interpolation 样条

样条过度可用于达到更现实的计时效果。由于动画通常用于模拟现实世界中发生的效果,因此您可能需要精确地控制对象的加速和减速,并且需要严格地对计时段进行操作,这时你就会用到样条关键帧。样条关键帧比起其他关键帧,多一个 KeySpline 属性,用于获取或设置用于定义此关键帧的动画进度的两个控制点。

若要了解 KeySpline 的工作原理,首先需要了解三次方贝塞尔曲线。一条三次方贝塞尔曲线由一个起点、一个终点和两个控制点来定义。

KeySpline 中的两个坐标定义这两个控制点。在描述关键样条时,贝塞尔曲线的起点始终为 0,终点始终为 1,这也就是只定义两个控制点的原因。所生成的曲线指定如何在一个时间段内内插动画;也就是说,该曲线表示该时间段内动画的目标属性的变化速率。

下面是来自MSDN的演示:

<SplineDoubleKeyFrame Value="500" 
  KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />
控制点为 (0.0, 1.0) 和 (1.0, 0.0) 的关键样条

Cc189038_JOLT_local_-624916683_graphicsmm_keyspline_0_1_1_0(zh-cn,VS_95)

上面的关键帧在开始时快速运动,再减速,然后再次加速,直到结束。

更多演示参看: http://msdn.microsoft.com/zh-cn/library/cc189038(VS.95).aspx 以及微软的演示 KeySpline 的例子,在这里可以看到:  运行此示例 

 

例子

下面我们先看一个简单例子:

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="MySilverlight3Study_Animation2.MainPage"
	Width="640" Height="480">
	<Canvas>
    <Canvas.Resources>
        <Storyboard x:Name="myStoryboard">
            <!-- 总共10秒钟的动画 -->
            <DoubleAnimationUsingKeyFrames
       Storyboard.TargetName="MyAnimatedTranslateTransform"
       Storyboard.TargetProperty="X"
       Duration="0:0:10">
                <!-- 0到3秒内,平滑过渡到 500  -->
                <LinearDoubleKeyFrame Value="500" KeyTime="0:0:3" />

                <!-- 在第4秒时,突然过度到 400 -->
                <DiscreteDoubleKeyFrame Value="400" KeyTime="0:0:4" />

                <!-- 从第4秒开始,逐步加速,一直到第8秒 -->
                <SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="0" KeyTime="0:0:8" />

   	        <!-- 第8秒到结束的第10秒,没有做任何事情  -->
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Canvas.Resources>

    <Rectangle MouseLeftButtonDown="Mouse_Clicked" Fill="BlueViolet"
 Width="50" Height="50">
        <Rectangle.RenderTransform>
            <TranslateTransform x:Name="MyAnimatedTranslateTransform" X="20" Y="20" />
        </Rectangle.RenderTransform>
    </Rectangle>
</Canvas>
</UserControl>

事件代码

private void Mouse_Clicked(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
	myStoryboard.Begin();
}

例子的演示效果如下,点击方块,开始动画:

 

代码说明:

我们对一个正方形的进行二维坐标平移来实现动画,动画是通过分帧的方式来定义实现的。

前3秒,平滑过渡,然后停下来,一直到第4秒,突然变化,然后加速运动。

LinearDoubleKeyFrame :  通过使用线性内插,可以在前一个关键帧的 Double 值及其自己的 Value 之间进行动画处理。

DiscreteDoubleKeyFrame  : 离散关键帧,在值之间产生突然"跳跃"(无内插算法)。换言之,已经过动画处理的属性在到达此关键帧的关键时间后才会更改,此时已经过动画处理的属性会突然转到目标值。

SplineDoubleKeyFrame : 通过 贝塞尔 曲线方式来定义动画变化节奏。详细看前面的介绍。

 

通过上面的代码,我们可以看到完成关键帧动画有以下3个步骤:

  • 首先声明一个Duration对象
  • 在每个节奏点上加入一个KeyFrame
  • 把动画效果和元素进行绑定

 

不同的属性类型有不同的动画类型。关键帧动画也是类似,如下是关键帧对应的分类。

属性类型 对应的关键帧动画类 支持的动画过渡方法
Color ColorAnimationUsingKeyFrames 离散、线性、样条
Double DoubleAnimationUsingKeyFrames 离散、线性、样条
Point PointAnimationUsingKeyFrames 离散、线性、样条
Object ObjectAnimationUsingKeyFrames 离散

ObjectAnimationUsingKeyFrames 很强大,我可以可以修改元素的任何属性,下面就是一个简单的例子:

例子使用了 ObjectAnimationUsingKeyFrames 对 Rectangle 的 Fill 属性进行动画处理。此动画按如下方式使用两个关键帧:

1.通过使用 DiscreteObjectKeyFrame,Rectangle 的 Fill 属性会在动画的前两秒之后突然更改为 LinearGradientBrush。

2.在动画的第三秒之后,Fill 属性会突然更改为另一个 LinearGradientBrush,然后一直保持到动画结束(总共四秒)。

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="MySilverlight3Study_Animation2.MainPage"
	Width="120" Height="120">
<StackPanel>
	<StackPanel.Triggers>
	 <EventTrigger RoutedEvent="StackPanel.Loaded">
	 	<BeginStoryboard>
		<Storyboard x:Name="myStoryboard">

            <ObjectAnimationUsingKeyFrames
         Storyboard.TargetName="animatedRectangle"
         Storyboard.TargetProperty="Fill"
         Duration="0:0:4" RepeatBehavior="Forever">
                <ObjectAnimationUsingKeyFrames.KeyFrames>
		    <!-- 2秒时突变 //-->
                    <DiscreteObjectKeyFrame KeyTime="0:0:2">
                        <DiscreteObjectKeyFrame.Value>
                            <LinearGradientBrush>
                                <LinearGradientBrush.GradientStops>
                                    <GradientStop Color="Yellow" Offset="0.0" />
                                    <GradientStop Color="Orange" Offset="0.5" />
                                    <GradientStop Color="Red" Offset="1.0" />
                                </LinearGradientBrush.GradientStops>
                            </LinearGradientBrush>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>

                    <!-- 3秒时再次突变 -->
                    <DiscreteObjectKeyFrame KeyTime="0:0:3">
                        <DiscreteObjectKeyFrame.Value>
                            <RadialGradientBrush GradientOrigin="0.75,0.25">
                                <RadialGradientBrush.GradientStops>
                                    <GradientStop Color="White" Offset="0.0" />
                                    <GradientStop Color="MediumBlue" Offset="0.5" />
                                    <GradientStop Color="Black" Offset="1.0" />
                                </RadialGradientBrush.GradientStops>
                            </RadialGradientBrush>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>

                </ObjectAnimationUsingKeyFrames.KeyFrames>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
		</BeginStoryboard>
        </EventTrigger>
	</StackPanel.Triggers>
    <!-- 我们将对这个正方形的 Fill 属性来做动画. -->
    <Rectangle x:Name="animatedRectangle" Width="100" Height="100" Fill="Aqua" Margin="10" />
</StackPanel>
</UserControl>

执行效果如下:

 

 

参考资料:

Animations
http://silverlight.net/learn/quickstarts/animations/

Silverlight 使用 XAML 和 Expression Blend 创建动画
http://msdn.microsoft.com/zh-cn/magazine/cc721608.aspx

关键帧动画
http://msdn.microsoft.com/zh-cn/library/cc189038(VS.95).aspx

稳扎稳打Silverlight(11) - 2.0动画之ColorAnimation, DoubleAnimation, PointAnimation, 内插关键帧动画
http://www.cnblogs.com/webabcd/archive/2008/11/06/1327758.html

使用 XAML 和 Expression Blend 创建动画
http://msdn.microsoft.com/zh-cn/magazine/cc721608.aspx

ObjectAnimationUsingKeyFrames 类
http://msdn.microsoft.com/zh-cn/library/system.windows.media.animation.objectanimationusingkeyframes(VS.95).aspx

posted on 2009-12-22 16:56:07 by ghj1976  评论(0) 阅读(1665)

 
2009年12月17日

按照动画的形成方式,Silverlight 动画可以分为两种:

  • 渐变风格方式(确定开始和结束,然后按照一个固定的频率完成渐变) ;
  • 关键帧生成方式 (设定若干中间帧,可以按照指定的节奏来变化,节奏可以忽快忽慢);

本文重点演示渐变风格方式。关键帧生成方式下篇再涉及。

要实现一个渐变风格动画,一般需要下面4步,我们下面的演示是实现一个小球从左到右来回移动的动画效果:

建立动画的4个步骤:
  • 创建一个对象并找到它。
    为了找到他,我们可以使用 x:Name 来给这个对象命名。为何是 x:Name  , 请参看我之前的博客: WPF,Silverlight 中的 xmlns,xmlns:x
    本文我们是一个红色的园球:
<Ellipse x:Name="ellipse" Height="20" Width="20" 
   Canvas.Left="31" Canvas.Top="31" Fill="#FFBE4343" >
</Ellipse>

 

  • 创建一个EventTrigger.
    EventTrigger 响应事件的一组触发器。 EventTrigger 对象将在发生指定的路由事件时启动一组 Actions。例如,当Silverlight加载成功后启动一组动画。
    EventTrigger 最重要的属性就是 RoutedEvent, 用于获取或设置将激活此触发器的 RoutedEvent。
    如果包含此 EventTrigger 的模板或样式没有指定 TargetType 属性,则需要使用 ClassName.EventName 语法通过类名限定事件名称。

目前Silverlight只支持一个事件:Element.Loaded,Element是包含trigger的对象的名称(这里是Canvas)。

<Canvas>
     <Canvas.Triggers>
        <EventTrigger RoutedEvent="Canvas.Loaded">
        </EventTrigger>
     </Canvas.Triggers>
     <Ellipse x:Name="ellipse" Height="20" Width="20" 
   	Canvas.Left="31" Canvas.Top="31" Fill="#FFBE4343" >
     </Ellipse>
</Canvas>

 

  • 使用 BeginStoryboard 和 Storyboard
    BeginStoryboard 是一个包含 Storyboard 对象的触发器操作,该操作可启动 Storyboard 并将其动画分发给动画的目标对象和属性。
    Storyboard 对象包含动画定义。 当定义动画时,您只需在 EventTrigger 定义内嵌入这些对象。
<Canvas>
    <Canvas.Triggers>
       	<EventTrigger RoutedEvent="Canvas.Loaded">
    	     <BeginStoryboard>
        	<Storyboard AutoReverse="True" RepeatBehavior="Forever">
        	</Storyboard>
             </BeginStoryboard>
        </EventTrigger>
    </Canvas.Triggers>
    <Ellipse x:Name="ellipse" Height="20" Width="20" 
   	Canvas.Left="31" Canvas.Top="31" Fill="#FFBE4343" >
    </Ellipse>
 </Canvas>

上面例子中的两个参数的意思分别如下:

AutoReverse: 获取或设置一个值,该值指示时间线在完成向前迭代后是否按相反的顺序播放。

RepeatBehavior : 获取或设置此时间线的重复行为。默认情况下,时间线的重复次数为 1.0,即播放一次时间线,不进行重复。但是,如果将 Timeline 的 RepeatBehavior 属性设置为 Forever,则时间线将会无限重复。

如果 AutoReverse 属性设置为 true 且 RepeatBehavior 值为 2x 的时间线将向前播放,然后向后播放,再向前播放,然后再向后播放,这样才算完。
除了指定时间线播放的次数,还可以指定希望时间线播放的总时间长度。如果 RepeatBehavior  的值为: 0:0:4 则表示要播放4秒钟。

 


  • 定义动画,

Storyboard  中增加下面代码:

<DoubleAnimation
    Storyboard.TargetName="ellipse"
    Storyboard.TargetProperty="(Canvas.Left)"
    To="500" Duration="0:0:3" />

这里的例子创建了一个DoubleAnimation动画,DoubleAnimation用于为包含双精度值的属性(例如,Canvas.Left 等维度属性或不透明度等可视化属性)设置动画效果。

上面例子中的参数的意思分别如下:

Storyboard.TargetName : 动画元素的名称(为此需要赋一个name属性),即第一步我们建立的那个元素。
Storyboard.TargetProperty : 动画元素的属性。
提示:Storyboard.TargetProperty的值是接收动态值的属性的名称,如果属性包含点(如Canvas.Left或Canvas.Top),
需要在圆括号内使用完整名称,如(Canvas.Left)或(Canvas.Top)。
Duration : 获取或设置此时间线播放的时间长度,而不是计数重复。语法为:hh:mm:ss(小时,分钟,秒)
To : 获取或设置动画的结束值。
设置双精度值动画效果时,可以在动画开始时使用 From 值指定该值,然后将其更改为 To 值(绝对目标),
或更改为 By 值(相对目标)。例如,如果要将某个项目的 Canvas.Left 属性从 100(接近屏幕的左端)移动至 500,
您可以将 From 值设置为 100,将 To 值设置为 500 或将 By 值设置为 400。请注意,如果您同时设置了 To 值和 By 值,
则优先采用 To 属性,而忽略 By 属性。同样,如果此矩形已经位于 From 的目标位置,则不需要再指定 From 属性。

除了 DoubleAnimation  渐变风格动画我们还可以使用 ColorAnimation ,PointAnimation 。ColorAnimation ,PointAnimation 动画中的 ByFromToDurationStoryboard.TargetNameStoryboard.TargetProperty含义类似。就不再重复含义介绍了。下面就是一个完整演示这三种动画的代码,演示效果看本文最后的演示:

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="MySilverlight3Study_Animation1.MainPage"
	Width="640" Height="300">
	<Canvas>
     <Canvas.Triggers>
        	<EventTrigger RoutedEvent="Canvas.Loaded">
        		<BeginStoryboard>
        			<Storyboard AutoReverse="True" RepeatBehavior="Forever">
        				<DoubleAnimation 
        					Storyboard.TargetName="ellipse"
        					Storyboard.TargetProperty="(Canvas.Left)"
        					To="500" Duration="0:0:3" />
					<ColorAnimation
						Storyboard.TargetName="rectangle"
						Storyboard.TargetProperty="(Fill).(Color)"
						To="Black" Duration="0:0:3" />
					<PointAnimation 
						Storyboard.TargetName="ellipseGeometry"
						Storyboard.TargetProperty="Center"
						By="400,-150" Duration="0:0:3" />	
        			</Storyboard>
        		</BeginStoryboard>
				
        	</EventTrigger>
        </Canvas.Triggers>
   	<Ellipse x:Name="ellipse" Height="20" Width="20" 
   		Canvas.Left="31" Canvas.Top="31" Fill="#FFBE4343" />
   	<Rectangle x:Name="rectangle" Fill="#FFC7CFE6" Height="31" Width="74" Canvas.Left="31" Canvas.Top="87"/>
	<Path Fill="Blue">
    	<Path.Data>
        	<EllipseGeometry x:Name="ellipseGeometry" Center="36,250" RadiusX="10" RadiusY="10" />
        </Path.Data>
    </Path>
   </Canvas>
</UserControl>

 

当然上面所有的代码都可以通过编程实现,但更多时候,我们只是编程实现 EventTrigger 和  BeginStoryboard 这部分,动画元素,故事板,动画定义我们是通过 Blend来编写 Xaml 文件来实现的。

 

参考资料:

Silverlight QuickStart:动画
http://www.cftea.com/docs/Silverlight/quickstart/animations-frames.html

Silverlight 使用 XAML 和 Expression Blend 创建动画
http://msdn.microsoft.com/zh-cn/magazine/cc721608.aspx

运行 Storyboard 时进行控制
http://msdn.microsoft.com/zh-cn/library/cc295328.aspx

触发器概述
http://msdn.microsoft.com/zh-cn/library/cc294856.aspx

silverlight 动画
http://www.cnblogs.com/njnudt/archive/2008/05/20/1203347.html

简单的Silverlight动画
http://www.cnblogs.com/nasa/archive/2009/06/04/silverlight-mpeo.html
稳扎稳打Silverlight(11) - 2.0动画之ColorAnimation, DoubleAnimation, PointAnimation, 内插关键帧动画
http://www.cnblogs.com/webabcd/archive/2008/11/06/1327758.html

程序效果如下:

posted on 2009-12-17 16:49:27 by ghj1976  评论(0) 阅读(2043)

 
2009年12月14日

其实反编译Silverlight 应用非常容易,下面就以反编译 http://www.joerassic.ch/  的街机对战的Silverlight应用为例来说明这个过程。http://www.joerassic.ch/ 有一个非常酷的,用Silverlight开发的恐龙街机对战的游戏,下面是一副截图。

image

 

下载Silverlight XAP文件:

由于 Silverlight 是在客户端浏览器中执行的,我们下载了 Silverlight 文件后,也就得到了完整的 Silverlight 执行文件。

当我们用 Internet Explorer 浏览器浏览了 Silverlight 应用后, 在Internet Explorer的临时文件夹中就有这个Silverlight的文件。我们可以直接来使用这个文件作为反编译的基础。Silverlight的文件是一个 xap 文件, 其实它就是一个 zip 文件。有关这部分的详细信息可以参看我之前写的博客: Silverlight项目中的文件

Internet Explorer  的临时文件夹可以通过下面菜单途径到达:

工具 --》 Internet 选项 打开 Internet 选项 设置Tab页。如下图:

image

在其中的 浏览历史记录中, 我们点击“设置” 按钮,进入了 Internet 临时文件和历史记录设置窗体,如下图:

image

在这个窗体中我们点击“查看文件”按钮,就可以进入临时文件目录。

临时文件目录下文件很多,由于silverlight 应用默认是 xap后缀的文件,我们通过过滤只看这类文件,如下图:

image

我们把上述 xap 文件另外复制一个目录,作为我们进一步反编译的基础。

注意,这个复制应该在 Internet Explorer 没有关闭 http://www.joerassic.ch/ 页面之前,同时Silverlight 加载之后进行,否则就会报错误:

image

我们把 xap 文件名的后缀修改为 zip , 然后解压缩到一个目录下。以这个街机对战的为例,解压缩后文件如下图,有关这些文件的用途,请参看我之前的博客:Silverlight项目中的文件

image

反编译:

由于Silverlight 2.0 以后, 大家几乎都是用 .net 来开发Siverlight 应用,我们也就可以使用 Reflector 打开其中的dll文件。

我们用 Reflector 打开 JurassicCombat.dll 文件后,查看Dll 反编译后的源代码很简单,如下图:

image

查看对应的XAML文件,则需要查看它的资源文件,如下图:

image

选中一个资源,然后右击,会出现“Save As” 菜单项,把这个资源另存在一个目录下,打开就可以看到 Xaml文件了, 当然上面资源文件中的图片文件,字体文件都可以看到。这个街机对战的恐龙动画特效文件并没有被编译到 Xap 文件中,而是另外有文件。我们在 Fiddler  辅助下就可以分析到这些图片文件的地址,这里使用的是 http://www.joerassic.ch/ClientBin/images.zip  http://www.joerassic.ch/ClientBin/images2.zip 的图片对应不同等级的对战特效。由于这些图片文件的巨大, 我们在访问 http://www.joerassic.ch/  的初始化时间才需要这么久。

posted on 2009-12-14 17:00:31 by ghj1976  评论(2) 阅读(2276)

 
2009年12月11日

我们来看例子,下面的椭圆显示的将不是完整的一个椭圆。

Xaml 文件:

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	x:Class="MySilverlight3StudyApplication.MainPage"
	Width="640" Height="480" mc:Ignorable="d">
		<Ellipse Stroke="Black" StrokeThickness="10" Height="64" 
		Margin="313,256,200,30" 
		VerticalAlignment="Top" HorizontalAlignment="Left" Width="197"/>
</UserControl>

执行效果如下图:

image

出现椭圆被劫了一部分的原因是 Margin="313,256,200,30"  在作怪。

Margin:获取或设置元素的外边距。上面的313,256,200,30 依次是 left,top,right,bottom

上面的右边距X坐标是通过下面算出来的 640(父控件宽度)-200(right Margin) = 440。 而正常椭圆的最右边点的X坐标为 313(left Margin)+10(left StrokeThickness)+197(Ellipse  Width)+10(right StrokeThickness)= 530。

由于椭圆的最右边已经在 计算出来的右边距之外了,在之外的部分就没有显示,所以就会有上面的情况发生。

posted on 2009-12-11 18:11:40 by ghj1976  评论(0) 阅读(1964)

 
2009年12月08日

这里通过简单的一个播放器代码来学习如何在silverlight中使用多媒体。代码是参考的 http://www.cnblogs.com/webabcd/archive/2009/11/10/1344632.html 的例子进行稍加改造完成的。执行效果见下图:视频播放的是我家宝宝7个月的时候的视频。

image

代码如下:

Xaml 文件:

说明:这里使用了 Grid  来控制布局。

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="SilverlightStudy.MainPage" Loaded="UserControl_Loaded">
    <Grid Height="500" Width="800">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="45" />
            <RowDefinition Height="90" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition Width="200"/>
        </Grid.ColumnDefinitions>
        <MediaElement x:Name="mediaElement" Grid.Row="0" Grid.ColumnSpan="4" Stretch="Fill" AutoPlay="False" 
            Source="http://localhost:41454/SilverlightStudySite/MVI_0122.mp4"
            BufferingProgressChanged="mediaElement_BufferingProgressChanged" MediaEnded="mediaElement_MediaEnded" 
            DownloadProgressChanged="mediaElement_DownloadProgressChanged" MediaOpened="mediaElement_MediaOpened" 
            CurrentStateChanged="mediaElement_CurrentStateChanged" />
        <Button x:Name="play" Content="播放" Margin="5" Grid.Row="1" Grid.Column="0" Click="play_Click" />
        <Button x:Name="pause" Content="暂停" Margin="5" Grid.Row="1" Grid.Column="1" Click="pause_Click" />
        <Button x:Name="stop" Content="停止" Margin="5" Grid.Row="1" Grid.Column="2" Click="stop_Click" />
        <Button x:Name="mute" Content="静音" Margin="5" Grid.Row="1" Grid.Column="3" Click="mute_Click" />
        <StackPanel Grid.Row="2" Grid.ColumnSpan="4">
            <Slider x:Name="playSlider" Minimum="0" Maximum="1" Margin="5" ToolTipService.ToolTip="播放进度" ValueChanged="playSlider_ValueChanged" />
            <Slider x:Name="volumeSlider" Minimum="0" Maximum="1" Margin="5" ToolTipService.ToolTip="音量大小" ValueChanged="volumeSlider_ValueChanged" />
            <Slider x:Name="balanceSlider" Minimum="-1" Maximum="1" Margin="5" ToolTipService.ToolTip="音量平衡" ValueChanged="balanceSlider_ValueChanged" />
        </StackPanel>
        <StackPanel  Grid.Column="4" Grid.RowSpan="3">
            <TextBlock x:Name="lblPlayTime" Margin="5" />
            <TextBlock x:Name="lblVolume" Margin="5" />
            <TextBlock x:Name="lblBalance" Margin="5" />
            <TextBlock x:Name="lblDownloadProgress" Margin="5" />
            <TextBlock x:Name="lblBufferingProgress" Margin="5" />
            <TextBlock x:Name="lblDroppedFramesPerSecond" Margin="5" />
            <TextBlock x:Name="lblState" Margin="5" />
            <TextBlock x:Name="lblWidth" Margin="5" />
            <TextBlock x:Name="lblHeight" Margin="5" />
            <TextBlock x:Name="lblTotalTime" Margin="5" />
            <TextBlock x:Name="lblBufferingTime" Margin="5" />
        </StackPanel>
    </Grid>
</UserControl>

 

 

对应的CS 文件,即事件处理代码。这里用了定时器,定时显示媒体的一些状态信息。

using System;
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.Threading;

namespace SilverlightStudy
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            // Required to initialize variables
            InitializeComponent();
        }

        /// <summary>
        /// 需要播放的文件的长度
        /// </summary>
        private TimeSpan _duration;


        /// <summary>
        /// 定时器,定时显示播放状态信息
        /// </summary>
        private DispatcherTimer _timer = new DispatcherTimer();


        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            // 每 500 毫秒调用一次指定的方法
            _timer.Interval = TimeSpan.FromMilliseconds(500);
            _timer.Tick += new EventHandler(_timer_Tick);
            _timer.Start();
        }


        void _timer_Tick(object sender, EventArgs e)
        {
            // CurrentState - 播放状态 [System.Windows.Media.MediaElementState枚举]
            // Position - 媒体的位置(单位:秒)
            if (mediaElement.CurrentState == MediaElementState.Playing)
            {
                lblPlayTime.Text = string.Format(
                    "{0}{1:00}:{2:00}:{3:00}",
                    "播放进度:",
                    mediaElement.Position.Hours,
                    mediaElement.Position.Minutes,
                    mediaElement.Position.Seconds);
            }

            // DroppedFramesPerSecond - 媒体每秒正在丢弃的帧数
            lblDroppedFramesPerSecond.Text = string.Format(
                "每秒丢弃帧数:{0}",
                mediaElement.DroppedFramesPerSecond);
        }

        private void mediaElement_BufferingProgressChanged(object sender, RoutedEventArgs e)
        {
            // BufferingProgress - 缓冲进度(0 - 1 之间)
            lblBufferingProgress.Text = string.Format(
                "缓冲进度:{0:##%}",
                mediaElement.BufferingProgress);

        }

        private void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
        {
            mediaElement.Stop();
        }

        private void mediaElement_DownloadProgressChanged(object sender, RoutedEventArgs e)
        {
            // DownloadProgress - 下载进度(0 - 1 之间)
            lblDownloadProgress.Text = string.Format(
                "下载进度:{0:##%}",
                mediaElement.DownloadProgress);

        }

        private void mediaElement_MediaOpened(object sender, RoutedEventArgs e)
        {
            /*
         * NaturalVideoWidth - 媒体文件的宽
         * NaturalVideoHeight - 媒体文件的高
         * HasTimeSpan - 是否可取得媒体文件的时长
         * NaturalDuration - 媒体文件的时长
         * Volume - 音量大小(0 - 1 之间)
         * Balance - 音量平衡(-1 - 1 之间)
         * BufferingTime - 需要缓冲的时间的长度
         */

            lblWidth.Text = "媒体文件的宽:" + mediaElement.NaturalVideoWidth.ToString();
            lblHeight.Text = "媒体文件的高:" + mediaElement.NaturalVideoHeight.ToString();

            _duration = mediaElement.NaturalDuration.HasTimeSpan ? mediaElement.NaturalDuration.TimeSpan : TimeSpan.FromMilliseconds(0);

            lblTotalTime.Text = string.Format(
                "时长:{0:00}:{0:00}:{0:00}",
                _duration.Hours,
                _duration.Minutes,
                _duration.Seconds);

            // 音量
            mediaElement.Volume = 0.8;
            volumeSlider.Value = 0.8;
            lblVolume.Text = "音量大小:80%";

            // 音量平和
            mediaElement.Balance = 0;
            balanceSlider.Value = 0;
            lblBalance.Text = "音量平衡:0%";

            // 缓存大小
            mediaElement.BufferingTime = TimeSpan.FromSeconds(30);
            lblBufferingTime.Text = "缓冲长度:30秒";

        }

        private void mediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
        {
            /*
         * CurrentState - 播放状态 [System.Windows.Media.MediaElementState枚举]
         *     MediaElementState.Closed - 无可用媒体
         *     MediaElementState.Opening - 尝试打开媒体(此时Play(),Pause(),Stop()命令会被排进队列,等到媒体被成功打开后再依次执行)
         *     MediaElementState.Buffering - 缓冲中
         *     MediaElementState.Playing - 播放中
         *     MediaElementState.Paused - 被暂停(显示当前帧)
         *     MediaElementState.Stopped - 被停止(显示第一帧)
         */

            lblState.Text = string.Format("播放状态:{0}", mediaElement.CurrentState);

        }


        private void play_Click(object sender, RoutedEventArgs e)
        {
            // Play() - 播放媒体(在当前 Position 处播放)
            mediaElement.Play();

        }

        private void stop_Click(object sender, RoutedEventArgs e)
        {
            // Stop() - 停止媒体的播放
            mediaElement.Stop();
        }

        private void pause_Click(object sender, RoutedEventArgs e)
        {
            // CanPause - 媒体是否可暂停
            // Pause() - 暂停媒体的播放
            if (mediaElement.CanPause)
                mediaElement.Pause();
        }

        private void mute_Click(object sender, RoutedEventArgs e)
        {
            // IsMuted - 是否静音
            if (mediaElement.IsMuted == true)
            {
                mute.Content = "静音";
                mediaElement.IsMuted = false;
            }
            else
            {
                mute.Content = "有声";
                mediaElement.IsMuted = true;
            }
        }

        private void playSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            // CanSeek - 是否可以通过设置 Position 来重新定位媒体
            // Position - 媒体的位置(单位:秒)
            if (mediaElement.CanSeek)
            {
                mediaElement.Pause();
                mediaElement.Position = TimeSpan.FromSeconds(_duration.TotalSeconds * playSlider.Value);
                mediaElement.Play();
            }

        }

        private void volumeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            // Volume - 音量大小(0 - 1 之间)
            mediaElement.Volume = volumeSlider.Value;
            lblVolume.Text = string.Format(
                "音量大小:{0:##%}",
                volumeSlider.Value);

        }

        private void balanceSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            // Balance - 音量平衡(-1 - 1 之间)
            mediaElement.Balance = balanceSlider.Value;
            lblBalance.Text = string.Format(
                "音量平衡:{0:##%}",
                balanceSlider.Value);

        }


    }
}

一些播放多媒体的知识点:

Silverlight 并非支持所有媒体格式和协议。

详细支持的媒体请参看: http://msdn.microsoft.com/zh-cn/library/cc189080(VS.95).aspx 

播放媒体的关键是 MediaElement 控件:这是一个表示包含音频和/或视频的控件。

MediaElement 的几个媒体特定的属性:

AutoPlay:指定 MediaElement 是否应自动开始播放。默认值为 true。

IsMuted:指定 MediaElement 是否静音。true 值将使 MediaElement 静音。默认值为 false。

Stretch:指定如何拉伸视频以填充 MediaElement 对象。可能值为 None、Uniform、UniformToFill 和 Fill。默认值为 Fill。

Balance: 音量平横,立体声扬声器的音量比。Double 类型属性,扬声器的音量比的范围为 -1 到 1。 默认值为 0。 值为 -1 表示左侧扬声器达到 100% 音量,而值为 1 表示右侧扬声器达到 100% 音量。0 表示在左右扬声器之间平均分布音量。

Volume: 音量大小。Double 类型属性,在 0 与 1 之间的线性标尺上所表示的媒体音量。 默认值为 0.5。

音量可能难以量化,因为每个媒体文件对于其录制或察觉到的音频级别都具有不同的基线。此外,真实的音量(以分贝标度表示)本质上是对数值。您可能希望用 Volume 属性来表示音频混频器滑块控件的位置,0 表示最低音量,而 1 表示最高音量。

Position : 自媒体开始播放之后经历的时间量。默认值是 TimeSpan 值"00:00:00"。可以设置的最大值是 MediaElement 对象的 NaturalDuration(媒体的自然持续时间)。

如果可以设置 Position,但该值被设置为某一负值或高于该媒体的 NaturalDuration 的值,则该属性值将相应设置为 00:00:00 或 NaturalDuration。

通常不应在 XAML 中设置此值,因为不能保证在加载媒体源之前可以定位该媒体。在引发 MediaOpened 后,检查 CanSeek 的值。如果该值为 true,则可以定位该媒体,并且可以设置 Position。

 

MediaElement 的事件说明:

MediaOpened: 当媒体流已被验证和打开且已读取文件头时发生。如果 AutoPlay 属性设置为 false,则当发生 MediaOpened 事件时,将暂停媒体。另外要注意: Position 属性在发生 MediaOpened 事件之前为 null。虽然 Position 是可设置的。但在引发 MediaOpened 事件之前,不应尝试设置 Position。包括不应在 XAML 中设置初始 Position 值。

MediaEnded : 当 MediaElement 对象不再播放音频或视频时发生。 如果媒体文件包含多个流,则在最后一个流结束后将发生 MediaEnded 事件。  如果以交互方式控制媒体播放,则不会发生 MediaEnded 事件。即上述演示代码中, mediaElement.Stop(); 不会触发 MediaEnded 事件。

CurrentStateChanged :   当 CurrentState 属性的值更改时发生。

尽管在 CurrentState 失效时会发生该事件,但这并不一定意味着 CurrentState 属性具有新值。例如,CurrentState 属性可能会从 Playing 切换为 Buffering 并很快又切换回 Playing,以致只引发了单个 CurrentStateChanged 事件,在这种情况下,该属性将并不表现为具有变化的值。此外,您的应用程序不应采用事件发生的顺序,尤其是针对"缓冲"之类的瞬态。在事件报告中可能会跳过某一瞬态,因为该瞬态发生得太快了。

DownloadProgressChanged :  在 DownloadProgress (MediaElement) 属性更改后发生。

对于渐进式下载,会发生 DownloadProgressChanged 事件(通常会发生多次)。只要下载的内容总量按照 0.05 或更高的量(作为 1.0 的系数,1.0 指示完成)增加或达到 1.0, 事件就会发生。

这里的 0.05, 是指 DownloadProgress 属性的值, DownloadProgress 属性是一个 Double 类型的属性,指示位于远程服务器上的内容的已下载内容的总量。此值介于 0 到 1 之间。乘以 100 可得到百分比。此属性为只读。默认值为 0。

BufferingProgressChanged : 当 BufferingProgress 属性更改时发生。

通常在下载过程中,BufferingProgressChanged 事件会发生多次。当 BufferingProgress 值按照 0.05 或更大的量增加(与上一次引发事件时相比)时,以及当该值达到 1.0 时,将发生该事件。

这里的 0.05, 是指 BufferingProgress  属性的值, BufferingProgress  属性是一个 Double 类型的属性,指示当前缓冲进度的值。此值介于 0 到 1 之间。乘以 100 可得到百分比。此属性为只读。默认值为 0。

 

参考资料:

稳扎稳打Silverlight(18) - 2.0视频之详解MediaElement, 开发一个简易版的全功能播放器
http://www.cnblogs.com/webabcd/archive/2009/11/10/1344632.html

音频和视频概述
http://msdn.microsoft.com/zh-cn/library/cc189078(VS.95).aspx

posted on 2009-12-08 17:21:04 by ghj1976  评论(0) 阅读(2052)

 
2009年12月04日

文本的处理

TextBlock 是 Silverlight 中的一个常用又有用的控件。我们可以通过TextBlock呈现只读的文本。

下面是演示代码

<UserControl
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="SilverlightStudy.MainPage"
	Width="640" Height="480">
  <TextBlock FontFamily="Arial Black" FontSize="16"
    Foreground="Red" Width="500">
	欢迎
         <Run FontSize="34" FontStyle="Italic" Foreground="Blue"></Run>
        <Run FontSize="22" FontStretch="ExtraCondensed">来到</Run>
        <Run>这里!</Run>
	<LineBreak />
	<Bold>哈哈哈哈</Bold>
	<Italic>我是谁?</Italic>
	<Underline>太阳出来了</Underline>
	<LineBreak />
  </TextBlock>
</UserControl>

演示效果:

image

其中一些属性如下:

FontFamily: Silverlight内置了十几种常见拉丁字体,如Arial,Comic Sans MS,Courier New,Lucida Sans Unicode等。默认使用的字体是 Portable User Interface。这是一种复合字体,它使用若干字体来实现 Silverlight 所支持的一组国际语言。这些字体包括针对许多西方书写系统的"Lucida Sans Unicode"和"Lucida Grande",以及针对东亚书写系统的更多字体。Silverlight 会根据文字的语言选择最佳的字体。

如果您指定的 FontFamily 不存在,即使它是唯一可用的字体系列值,Silverlight 仍将为 Portable User Interface 值提供备用值以用于呈现。

上面例子中,我把字体设置成 Arial Black,由于其中的中文无法找到对应字体,就使用了 Portable User Interface  来显示的。由于是中文,上述文字就是用宋体的样式来显示的。

如果我们直接把字体修改为其他中文字体,比如: 微软雅黑, 程序就会报警告:

The font, 微软雅黑, is not a built-in Silverlight font and will not be displayed to users who run your Silverlight application.  To display the font, either install the font on your computer and then use Expression Blend to embed the font in your project, or add the font files to your project.   

如何解决这个问题以及关于字体的更多信息,你可以看下面几篇文章: 
文本和字体: http://msdn.microsoft.com/zh-cn/library/cc189010(VS.95).aspx 

解决Silverlight引用中文字体的问题

http://blog.joycode.com/joy/archive/2007/05/28/103441.aspx

Silverlight Tip of the Day #46 – Font Support in Silverlight

FontSize:指定所需字体大小(以像素为单位)。值必须为非负数。 默认值为 11 像素。

FontStretch: 指定所需的字体标志符号宽度。

默认值为 Normal。FontStretch 的效果依赖于正使用的特定字体系列,并且只能指定字体系列中已经存在的字体。该属性不会导致以编程方式拉伸标志符号。(注意:如果 FontStretch 映射不可用,您可以考虑将某一变换应用于文本。)

压缩或者拉长的比率请参看下面文档

http://msdn.microsoft.com/zh-cn/library/system.windows.fontstretches(VS.95).aspx

FontStyle: 指定所需字形为普通还是斜体。
可设置两种值: Normal, Italic(斜体)。默认值为 Normal。FontWeight 的效果依赖于正使用的特定字体系列,并且通常只能指定字体系列中已经存在的字体。Silverlight 不以编程方式创建修剪变形来模拟斜体。

FontWeight: 指定所需的字体标志符号粗细。即:文字的胖瘦。可设置为Thin, ExtraLight, Light, Normal, Medium, SemiBold, Bold, ExtraBold, Black, ExtraBlack.这些值是否起作用还要取决于你所选择的字体。默认值为 Normal。

FontWeight 的效果依赖于正使用的特定字体系列,并且通常只能指定字体系列中已经存在的字体。修剪不会以编程方式创建备用粗细值,除非字体系列中包含普通粗细字体,而不包含粗体字体。在这种情况下,Silverlight 将通过增加使用二维图形算法的笔画宽度来模拟粗体字体。

TextDecorations: 对文字的修饰,默认设置为无修饰。若要指定下划线修饰,请将 TextDecorations 属性设置为 Underline。

Foreground:  通过这个属性可以设置文字的前景色填充。不但可以使用颜色值,还可以通过设置solid color, gradient, image 及 video笔刷进行填充。

比如下面代码就是使用的图片做的文字前景刷子

<TextBlock Text="SHRUBBERY">
  <TextBlock.Foreground>
    <ImageBrush ImageSource="forest.jpg"/>
  </TextBlock.Foreground>
</TextBlock>

执行效果:

image

Run:   你可以在TextBlock中使用Run标签创建内联元素,每个Run都可以设置上面提到的属性。这样一篇文档,就可以每处显示的风格都不一样。

 

参考资料:

了解Silverlight提供的TextBlock(文字区块)元素对象
http://silverlight.cn/node/356

[Silverlight]TextBlock控件全攻略
http://www.cnblogs.com/024hi/archive/2008/12/04/1347337.html

文本和字体
http://msdn.microsoft.com/zh-cn/library/cc189010(VS.95).aspx

WPF4数据绑定应用之创建具有多种显示效果的字串
http://www.cnblogs.com/bitfan/archive/2009/11/12/1601857.html

posted on 2009-12-04 14:08:23 by ghj1976  评论(0) 阅读(2029)

 
【第1页/共19页,655条】
首页
前页
1
...

Powered by: Joycode.MVC引擎 0.5.2.0