SnipperImages(Silverlight DEMO)控件设计之--ImageSelector

     在SnipperImages中为了进行图片列表导航(前后方向)设计了ImageSelector控件,而这个控件不同于
之前介绍过的Button, CheckBox, Slider,主要是其xaml中的UI元素变得数量庞大且行为更加复杂。所以通过
了解这个控件,我们能够更好的熟悉StoryBoard,Path,ImageBrush,ScaleTransform,TranslateTransform
等对象及属性的使用场景。

  首先来看一下DEMO运行效果:
 
 


     显示一张图片所使用的ui元素如下所示(其中之一):

< Path  x:Name ="leftImg3"  Stroke ="White"  MouseLeftButtonDown ="OnImgClicked" >
  
< Path.Data >
    
< PathGeometry >
      
< PathFigure  x:Name ="pathFigure_leftImg3"  IsClosed ="True"  StartPoint ="130,15" >
        
< LineSegment  x:Name ="line1_leftImg3"  Point ="250,25" />
        
< LineSegment  x:Name ="line2_leftImg3"  Point ="250,95" />
        
< LineSegment  x:Name ="line3_leftImg3"  Point ="130,115" />
      
</ PathFigure >
    
</ PathGeometry >
  
</ Path.Data >
  
< Path.Fill >
    
< ImageBrush  x:Name ="leftImg3Brush"  Stretch ="Fill" />
  
</ Path.Fill >
</ Path >


     大家发现了,上面的内容只是可以正常显示一个图像(通过设置leftImg3Brush的ImageSource属性)而
在每一个图片下方都会有一个倒影效果,其使用的就是ScaleTransform,其代码布局如下:

  < Path  x:Name ="left3Reflection"  Stroke ="White" >
      
< Path.Data >
        
< PathGeometry >
          
< PathFigure  x:Name ="pathFigure_left3Reflection"  IsClosed ="True"  StartPoint ="130,120" >
            
< LineSegment  x:Name ="line1_left3Reflection"  Point ="250,100" />
            
< LineSegment  x:Name ="line2_left3Reflection"  Point ="250,170" />
            
< LineSegment  x:Name ="line3_left3Reflection"  Point ="130,190" />
          
</ PathFigure >
        
</ PathGeometry >
      
</ Path.Data >
      
< Path.Fill >
        
< ImageBrush  x:Name ="leftReflection3Brush"  Stretch ="Fill" >
          
< ImageBrush.RelativeTransform >
            
< TransformGroup >
              
<!-- 实现投影效果 -->
              
< ScaleTransform  ScaleX ="1"  ScaleY ="-1"   />
              
< TranslateTransform  Y ="1"   />
            
</ TransformGroup >
          
</ ImageBrush.RelativeTransform >
        
</ ImageBrush >
      
</ Path.Fill >
      
< Path.OpacityMask >
        
< LinearGradientBrush  StartPoint ="0.5,0"  EndPoint ="0.5,1" >
          
< LinearGradientBrush.GradientStops >
            
< GradientStop  Offset ="0.0"  Color ="#2F000000"   />
            
< GradientStop  Offset ="1.0"  Color ="#00000000"   />
          
</ LinearGradientBrush.GradientStops >
        
</ LinearGradientBrush >
      
</ Path.OpacityMask >
    
</ Path >

     
      而有关如何实现倒影效果可以参考 这篇文章。当然如果使用BLEND来制作倒影效果会更容易,但不知道为
什么,目前的BLEND还无法实现对子对象的属性设置(因为上面的XAML代码被放在了PATH对象中,而BLEND
在可视状态下只能看到PATH那一层的对象,而无法设置ImageBrush="leftReflection2Brush"这个对象)。

     有了7个path对象加载图像(使用里面的ImageBrush的ImageSource属性)。还有7个path对象分别对应
实现7个图像的倒影效果。也就是下图中所显示的:
 
 


     当然除此以外,还有2组PATH对象分别是:
   lastImgBrush,lastReflectionBrush:用于当点击右侧导航按钮时,设置为当前分页下最右侧图像,以
                                                避免出现图片为空(空框)的情况。
     firstImgBrush,firstReflectionBrush:用于当点击左侧导航按钮时,设置为当前分页下最左侧图像,以
                   避免出现图片为空(空框)的情况。
                   
     有了这些静态的UI元素之后,我们还需要让其动起来,所以要用到StoryBoard(故事板)。而有关该内容
介绍可参见如下链接: 使用silverlight中的Storyboard实现动画效果

     因为本DEMO中用的是PointAnimation(当动画值的变化[FROM ...TO...]类型是 Point型时使用), 所以这
里直接就把相应的Xaml代码放在这里了,代码很简单。
     首先是当点击右侧导航按钮时的Storyboard代码:  

Code
<Storyboard x:Name='flowForward' Completed='onForwardFlowCompleted'>
        
<PointAnimation Storyboard.TargetName='pathFigure_centerImg' Storyboard.TargetProperty='StartPoint' From='250,15' To='330,5' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_centerImg' Storyboard.TargetProperty='Point' From='370,25' To='470,5' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_centerImg' Storyboard.TargetProperty='Point' From='370,95' To='470,145' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_centerImg' Storyboard.TargetProperty='Point' From='250,115' To='330,145' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_centerReflection' Storyboard.TargetProperty='StartPoint' From='250,120' To='330,155' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_centerReflection' Storyboard.TargetProperty='Point' From='370,100' To='470,155' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_centerReflection' Storyboard.TargetProperty='Point' From='370,170' To='490,195' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_centerReflection' Storyboard.TargetProperty='Point' From='250,190' To='310,195' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_rightImg1' Storyboard.TargetProperty='StartPoint' From='330,5' To='430,25' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_rightImg1' Storyboard.TargetProperty='Point' From='470,5' To='550,15' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_rightImg1' Storyboard.TargetProperty='Point' From='470,145' To='550,115' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_rightImg1' Storyboard.TargetProperty='Point' From='330,145' To='430,95' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_right1Reflection' Storyboard.TargetProperty='StartPoint' From='330,155' To='430,100' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_right1Reflection' Storyboard.TargetProperty='Point' From='470,155' To='550,120' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_right1Reflection' Storyboard.TargetProperty='Point' From='490,195' To='550,190' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_right1Reflection' Storyboard.TargetProperty='Point' From='310,195' To='430,170' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_rightImg2' Storyboard.TargetProperty='StartPoint' From='430,25' To='500,25' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_rightImg2' Storyboard.TargetProperty='Point' From='550,15' To='620,15' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_rightImg2' Storyboard.TargetProperty='Point' From='550,115' To='620,115' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_rightImg2' Storyboard.TargetProperty='Point' From='430,95' To='500,95' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_right2Reflection' Storyboard.TargetProperty='StartPoint' From='430,100' To='500,100' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_right2Reflection' Storyboard.TargetProperty='Point' From='550,120' To='620,120' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_right2Reflection' Storyboard.TargetProperty='Point' From='550,190' To='620,190' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_right2Reflection' Storyboard.TargetProperty='Point' From='430,170' To='500,170' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_rightImg3' Storyboard.TargetProperty='StartPoint' From='500,25' To='550,25' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_rightImg3' Storyboard.TargetProperty='Point' From='620,15' To='670,15' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_rightImg3' Storyboard.TargetProperty='Point' From='620,115' To='670,115' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_rightImg3' Storyboard.TargetProperty='Point' From='500,95' To='550,95' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_right3Reflection' Storyboard.TargetProperty='StartPoint' From='500,100' To='550,100' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_right3Reflection' Storyboard.TargetProperty='Point' From='620,120' To='670,120' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_right3Reflection' Storyboard.TargetProperty='Point' From='620,190' To='670,190' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_right3Reflection' Storyboard.TargetProperty='Point' From='500,170' To='550,170' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_leftImg1' Storyboard.TargetProperty='StartPoint' From='180,15' To='250,15' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_leftImg1' Storyboard.TargetProperty='Point' From='300,25' To='370,25' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_leftImg1' Storyboard.TargetProperty='Point' From='300,95' To='370,95' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_leftImg1' Storyboard.TargetProperty='Point' From='180,115' To='250,115' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_left1Reflection' Storyboard.TargetProperty='StartPoint' From='180,120' To='250,120' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_left1Reflection' Storyboard.TargetProperty='Point' From='300,100' To='370,100' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_left1Reflection' Storyboard.TargetProperty='Point' From='300,170' To='370,170' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_left1Reflection' Storyboard.TargetProperty='Point' From='180,190' To='250,190' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_leftImg2' Storyboard.TargetProperty='StartPoint' From='130,15' To='180,15' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_leftImg2' Storyboard.TargetProperty='Point' From='250,25' To='300,25' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_leftImg2' Storyboard.TargetProperty='Point' From='250,95' To='300,95' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_leftImg2' Storyboard.TargetProperty='Point' From='130,115' To='180,115' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_left2Reflection' Storyboard.TargetProperty='StartPoint' From='130,120' To='180,120' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_left2Reflection' Storyboard.TargetProperty='Point' From='250,100' To='300,100' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_left2Reflection' Storyboard.TargetProperty='Point' From='250,170' To='300,170' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_left2Reflection' Storyboard.TargetProperty='Point' From='130,190' To='180,190' Duration='0:0:0.5'/>
</Storyboard>
      
      然后是点击左侧导航时的StoryBoard代码:     
     
Code
<Storyboard x:Name='flowBackward' Completed='onBackwardFlowCompleted'>
        
<PointAnimation Storyboard.TargetName='pathFigure_centerImg' Storyboard.TargetProperty='StartPoint' From='430,25' To='330,5' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_centerImg' Storyboard.TargetProperty='Point' From='550,15' To='470,5' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_centerImg' Storyboard.TargetProperty='Point' From='550,115' To='470,145' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_centerImg' Storyboard.TargetProperty='Point' From='430,95' To='330,145' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_centerReflection' Storyboard.TargetProperty='StartPoint' From='430,100' To='330,155' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_centerReflection' Storyboard.TargetProperty='Point' From='550,120' To='470,155' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_centerReflection' Storyboard.TargetProperty='Point' From='550,190' To='490,195' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_centerReflection' Storyboard.TargetProperty='Point' From='430,170' To='310,195' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_leftImg1' Storyboard.TargetProperty='StartPoint' From='330,5' To='250,15' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_leftImg1' Storyboard.TargetProperty='Point' From='470,5' To='370,25' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_leftImg1' Storyboard.TargetProperty='Point' From='470,145' To='370,95' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_leftImg1' Storyboard.TargetProperty='Point' From='330,145' To='250,115' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_left1Reflection' Storyboard.TargetProperty='StartPoint' From='330,155' To='250,120' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_left1Reflection' Storyboard.TargetProperty='Point' From='470,155' To='370,100' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_left1Reflection' Storyboard.TargetProperty='Point' From='490,195' To='370,170' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_left1Reflection' Storyboard.TargetProperty='Point' From='310,195' To='250,190' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_leftImg2' Storyboard.TargetProperty='StartPoint' From='250,15' To='180,15' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_leftImg2' Storyboard.TargetProperty='Point' From='370,25' To='300,25' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_leftImg2' Storyboard.TargetProperty='Point' From='370,95' To='300,95' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_leftImg2' Storyboard.TargetProperty='Point' From='250,115' To='180,115' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_left2Reflection' Storyboard.TargetProperty='StartPoint' From='250,120' To='180,120' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_left2Reflection' Storyboard.TargetProperty='Point' From='370,100' To='300,100' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_left2Reflection' Storyboard.TargetProperty='Point' From='370,170' To='300,170' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_left2Reflection' Storyboard.TargetProperty='Point' From='250,190' To='180,190' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_leftImg3' Storyboard.TargetProperty='StartPoint' From='180,15' To='130,15' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_leftImg3' Storyboard.TargetProperty='Point' From='300,25' To='250,25' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_leftImg3' Storyboard.TargetProperty='Point' From='300,95' To='250,95' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_leftImg3' Storyboard.TargetProperty='Point' From='180,115' To='130,115' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_left3Reflection' Storyboard.TargetProperty='StartPoint' From='180,120' To='130,120' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_left3Reflection' Storyboard.TargetProperty='Point' From='300,100' To='250,100' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_left3Reflection' Storyboard.TargetProperty='Point' From='300,170' To='250,170' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_left3Reflection' Storyboard.TargetProperty='Point' From='180,190' To='130,190' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_rightImg1' Storyboard.TargetProperty='StartPoint' From='500,25' To='430,25' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_rightImg1' Storyboard.TargetProperty='Point' From='620,15' To='550,15' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_rightImg1' Storyboard.TargetProperty='Point' From='620,115' To='550,115' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_rightImg1' Storyboard.TargetProperty='Point' From='500,95' To='430,95' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_right1Reflection' Storyboard.TargetProperty='StartPoint' From='500,100' To='430,100' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_right1Reflection' Storyboard.TargetProperty='Point' From='620,120' To='550,120' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_right1Reflection' Storyboard.TargetProperty='Point' From='620,190' To='550,190' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_right1Reflection' Storyboard.TargetProperty='Point' From='500,170' To='430,170' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_rightImg2' Storyboard.TargetProperty='StartPoint' From='550,25' To='500,25' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_rightImg2' Storyboard.TargetProperty='Point' From='670,15' To='620,15' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_rightImg2' Storyboard.TargetProperty='Point' From='670,115' To='620,115' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_rightImg2' Storyboard.TargetProperty='Point' From='550,95' To='500,95' Duration='0:0:0.5'/>

        
<PointAnimation Storyboard.TargetName='pathFigure_right2Reflection' Storyboard.TargetProperty='StartPoint' From='550,100' To='500,100' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line1_right2Reflection' Storyboard.TargetProperty='Point' From='670,120' To='620,120' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line2_right2Reflection' Storyboard.TargetProperty='Point' From='670,190' To='620,190' Duration='0:0:0.5'/>
        
<PointAnimation Storyboard.TargetName='line3_right2Reflection' Storyboard.TargetProperty='Point' From='550,170' To='500,170' Duration='0:0:0.5'/>
</Storyboard>
      
      
    上面的两块xaml代码分别操作UI元素(注意只有六组,而不是七组,因为整体动态效果用六组PATH对象移动即可实现)。
 
    注:目前无法在BLEND下对两个StoryBoard的运行效果进行设计测试,也就是之前BLEND截图中箭头所指示的
"No StoryBoard Open",造成这个问题的原因目前我还不大清楚,有兴趣的朋友不妨也帮助分析一下原因。
    
    到这里,页面上的图象展示元素和StoryBoard就介绍完了,当然还有两个按钮控件(RepeatButton类型)没有介绍,因为
其功能只是实现按钮事件触发Storyboard运行,而且有关Button按钮控件的类继承关系及设计原理我之前已写过一篇文章作
了一些介绍,大家参考一下即可。

     好了,xaml内容介绍完了,下面介绍一下CS代码,首先是事件参数声明(详细内容见注释):

///   <summary>
///  ImageSelector事件参数
///   </summary>
public   class  ImageSelectedEventArgs : EventArgs
{
        
///   <summary>
        
///  当前选择的图片源信息
        
///   </summary>
         public   string  Source;
        
///   <summary>
        
///  当前选择的图片位图对象
        
///   </summary>
         public  BitmapImage ImageSource;
}

    
    然后是选择图片时的事件处理句柄(关于使用参见接下来的代码):
    
     ///   <summary>
    
///  ImageSelected事件处理句柄
    
///   </summary>
    
///   <param name="sender"></param>
    
///   <param name="e"></param>
     public   delegate   void  ImageSelectedEventHandler( object  sender, ImageSelectedEventArgs e);


     接着是控件的主体类了(详情见注释):

///   <summary>
///  ImageSelector控件类
///   </summary>
public   partial   class  ImageSelector : UserControl
{
     
///   <summary>
     
///  声明ImageSelected事件处理句柄的实例
     
///   </summary>
      public   event  ImageSelectedEventHandler ImageSelected;

     
public  ImageSelector()
     {
         InitializeComponent();

         
// 图像刷数组初始化,用于绑定指定的BitmapImage信息
         imageBrushArray  =   new  ImageBrush[ 7 ]; // 7为当前页图片数
         imageBrushArray[ 0 =  leftImg3Brush;
         imageBrushArray[
1 =  leftImg2Brush;
         imageBrushArray[
2 =  leftImg1Brush;
         imageBrushArray[
3 =  centerImgBrush;
         imageBrushArray[
4 =  rightImg1Brush;
         imageBrushArray[
5 =  rightImg2Brush;
         imageBrushArray[
6 =  rightImg3Brush;

         
// “倒影效果”图像刷数组初始化,用于绑定指定的BitmapImage信息
         reflectionBrushArray  =   new  ImageBrush[ 7 ]; // 7为当前页图片数
         reflectionBrushArray[ 0 =  leftReflection3Brush;
         reflectionBrushArray[
1 =  leftReflection2Brush;
         reflectionBrushArray[
2 =  leftReflection1Brush;
         reflectionBrushArray[
3 =  centerReflectionBrush;
         reflectionBrushArray[
4 =  rightReflection1Brush;
         reflectionBrushArray[
5 =  rightReflection2Brush;
         reflectionBrushArray[
6 =  rightReflection3Brush;

         
// 绑定鼠标点击图片(外侧Path对象)后的事件
         leftImg3.MouseLeftButtonDown  +=   new  MouseButtonEventHandler(OnImgClicked);
         leftImg2.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(OnImgClicked);
         leftImg1.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(OnImgClicked);
         rightImg3.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(OnImgClicked);
         rightImg2.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(OnImgClicked);
         rightImg1.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(OnImgClicked);
         centerImg.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(OnImgClicked);
     }

     
///   <summary>
     
///  定义图像点击事件
     
///   </summary>
     
///   <param name="sender"></param>
     
///   <param name="e"></param>
      void  OnImgClicked( object  sender, MouseButtonEventArgs e)
     {
         ImageSelectedEventArgs args 
=   new  ImageSelectedEventArgs();
         
// 设置事件参数
         args.ImageSource  =  ((Path)sender).Fill.GetValue(ImageBrush.ImageSourceProperty)  as  BitmapImage;
         
// 调用图片选择事件
         OnImageSelected(args);
     }

     
///   <summary>
     
///  定义图片选择事件
     
///   </summary>
     
///   <param name="e"></param>
      protected   void  OnImageSelected(ImageSelectedEventArgs e)
     {
         
if  (ImageSelected  !=   null )
         {
             
// 调用绑定的处理事件代码
             ImageSelected( this , e);
         }
     }

     
///   <summary>
     
///  实始化图像数组并绑定相应的图像Brush
     
///   </summary>
     
///   <param name="imageUris"> 图片路径信息 </param>
      public   void  SetImages( string [] imageUris)
     {
         imageArray 
=  imageUris;
         
if  (imageArray.Length  >=   7 )
         {
             
// 设置当前显示的图片数组的左起索引数
             imageIndex  =   0 ;
             
// 绑定相应的图像Brush
             UpdateImages();
         }
     }

    
     
///   <summary>
     
///  定义“flowForward(前进)”对象(Storyboard类型) 的Completed处理事件
     
///   </summary>
     
///   <param name="sender"></param>
     
///   <param name="e"></param>
      void  onForwardFlowCompleted( object  sender, EventArgs e)
     {  
         
// 当storyboard动画效果完成时置为NULL
         firstImgBrush.ImageSource  =   null ;
         lastImgBrush.ImageSource 
=   null ;
         firstReflectionBrush.ImageSource 
=   null ;
         lastReflectionBrush.ImageSource 
=   null ;
     }

     
///   <summary>
     
///  定义“flowBackward(后退)”对象(Storyboard类型) 的Completed处理事件
     
///   </summary>
     
///   <param name="sender"></param>
     
///   <param name="e"></param>
      void  onBackwardFlowCompleted( object  sender, EventArgs e)
     {
         
// 当storyboard动画效果完成时置为NULL
         firstImgBrush.ImageSource  =   null ;
         lastImgBrush.ImageSource 
=   null ;
         firstReflectionBrush.ImageSource 
=   null ;
         lastReflectionBrush.ImageSource 
=   null ;
     }

     
///   <summary>
     
///  “后退”按钮点击事件
     
///   </summary>
     
///   <param name="sender"></param>
     
///   <param name="e"></param>
      void  btnBack_Click( object  sender, EventArgs e)
     {
         
if  (imageIndex  !=   - 1 )
         {
             
// 更新最左侧图像刷和“倒影”对象,使其在下面storyboard运动过程中逐渐被遮盖
             firstImgBrush.ImageSource  =   new  BitmapImage( new  Uri(imageArray[imageIndex], 
                                                                                       UriKind.RelativeOrAbsolute));
 
 
             firstReflectionBrush.ImageSource  =   new  BitmapImage( new  Uri(imageArray[imageIndex], 
                                                                                       UriKind.RelativeOrAbsolute));

             
// 注:后退方向与我们通常认为的方向相反(通常是imageIndex--),这块不知道是作者的疏忽还是别的原因
             imageIndex ++ ;
             
if  (imageIndex  ==  imageArray.Length)
             {
                 imageIndex 
=   0 ;
             }
             UpdateImages();
             
// 运行"后退"storyboard效果
             flowBackward.Begin();
         }
     }

     
///   <summary>
     
///  “前进”按钮点击事件
     
///   </summary>
     
///   <param name="sender"></param>
     
///   <param name="e"></param>
      void  btnForward_Click( object  sender, EventArgs e)
     {            
         
if  (imageIndex  !=   - 1 )
         {
             
// 更新最右侧图像刷和“倒影”对象,使其在下面storyboard运动过程中逐渐被遮盖
             lastImgBrush.ImageSource  =   new  BitmapImage( new  Uri(imageArray[(imageIndex  +   6 %  
                                                                        imageArray.Length], UriKind.RelativeOrAbsolute));
 
 
             lastReflectionBrush.ImageSource  =   new  BitmapImage( new  Uri(imageArray[(imageIndex  +   6 %  
                                                                        imageArray.Length], UriKind.RelativeOrAbsolute));

             
// 注:前进方向与我们通常认为方向相反(通常是imageIndex++),这块不知道是作者的疏忽还是别的原因
             imageIndex -- ;
             
if  (imageIndex  <   0 )
             {
                 imageIndex 
=  imageArray.Length  -   1 ;
             }
             UpdateImages();
             
// 运行"前进"storyboard效果
             flowForward.Begin();
         }           
     }

     
///   <summary>
     
///  绑定相应的图像Brush
     
///   </summary>
      void  UpdateImages()
     {
         
int  brushIndex  =  imageIndex;
         
for  ( int  i  =   0 ; i  <   7 ; i ++ )
         {
             
// 加载图像信息
             imageBrushArray[i].ImageSource  =   new  BitmapImage( new  Uri(imageArray[brushIndex], 
                                                                                              UriKind.RelativeOrAbsolute));
 
 
             reflectionBrushArray[i].ImageSource  =   new  BitmapImage( new  Uri(imageArray[brushIndex], 
                                                                                              UriKind.RelativeOrAbsolute));
 
 
             brushIndex ++ ;
             
// 当到达最大长度时,则清零(回到起始位置,实现循环效果)
              if  (brushIndex  ==  imageArray.Length)
             {
                 brushIndex 
=   0 ;
             }
         }
     }
    

     
///   <summary>
     
///  图像刷数组用于绑定(显示)指定的BitmapImage信息
     
///   </summary>
      private  ImageBrush[] imageBrushArray;
     
///   <summary>
     
///  "倒影"效果图像刷数组
     
///   </summary>
      private  ImageBrush[] reflectionBrushArray;
     
///   <summary>
     
///  图片路径信息数组
     
///   </summary>
      private   string [] imageArray;
     
///   <summary>
     
///  当前显示的图片数组的左起索引数
     
///   </summary>
      private   int  imageIndex  =   - 1 ;
}

     上面的控件类主要是实现了初始化属性成员(图片数组)和相应UI元素事件的绑定(MouseLeftButtonDown),
然后是相应的事件处理代码(前进,后退按钮事件)。当然在实现上我个人认为还有一些问题(在注释中已说明)。
但总体上代码布局还是很清爽的。

     下面即是本文开头DEMO页面的xaml代码(源码包中的Page3.xaml):

Code
   <!--控件声明-->
 
<ctl:ImageSelector x:Name='imageSelector' ImageSelected='OnImageSelected' Canvas.Top='400' Loaded='imageSelector_Loaded'/>

        
<!--当用户点某一图片时显示元素-->
        
<InkPresenter x:Name="snipCanvas" Background="#80F5F5DC" Opacity="0" Canvas.Left="100" Canvas.Top="70" Width="600" Height="430" Cursor="Hand">
            
<InkPresenter.Resources>
                
<Storyboard x:Name="snipCanvasFadeIn">
                    
<DoubleAnimation Storyboard.TargetName="snipCanvas" Storyboard.TargetProperty="Opacity" From="0.0" To="1.0" Duration='0:0:0.5'/>
                    
<DoubleAnimation Storyboard.TargetName="snipCanvasScale" Storyboard.TargetProperty="ScaleX" From="0.0" To="1.0" Duration='0:0:0.5'/>
                    
<DoubleAnimation Storyboard.TargetName="snipCanvasScale" Storyboard.TargetProperty="ScaleY" From="0.0" To="1.0" Duration='0:0:0.5'/>
                
</Storyboard>
                
<Storyboard x:Name="snipCanvasFadeOut">
                    
<DoubleAnimation Storyboard.TargetName="snipCanvas" Storyboard.TargetProperty="Opacity" From="1.0" To="0.0" Duration='0:0:0.5'/>
                    
<DoubleAnimation Storyboard.TargetName="snipCanvasScale" Storyboard.TargetProperty="ScaleX" From="1.0" To="0.0" Duration='0:0:0.5'/>
                    
<DoubleAnimation Storyboard.TargetName="snipCanvasScale" Storyboard.TargetProperty="ScaleY" From="1.0" To="0.0" Duration='0:0:0.5'/>
                
</Storyboard>
            
</InkPresenter.Resources>
            
<InkPresenter.RenderTransform>
                
<ScaleTransform x:Name="snipCanvasScale" ScaleX="0.0" ScaleY="0.0" CenterX="300" CenterY="215"/>
            
</InkPresenter.RenderTransform>

            
<Canvas Canvas.Left="577" Canvas.Top="3" Width="20" Height="20" Background="Crimson" MouseLeftButtonUp="onExitMouseUp">
                
<Line X1="4" Y1="4" X2="16" Y2="16" Stroke="White" StrokeThickness="3" />
                
<Line X1="16" Y1="4" X2="4" Y2="16" Stroke="White" StrokeThickness="3" />
            
</Canvas>
            
<Image x:Name="snipImage" Canvas.Left="10" Canvas.Top="40"
                       Width
="580" Height="380" Stretch="Uniform" />
             
        
</InkPresenter>

     而相应的CS代码如下所示:

void  imageSelector_Loaded( object  sender, RoutedEventArgs e)
{

    
string  baseUri  =   Application.Current.Host.Source.AbsoluteUri.Substring( 0 ,
                                                       Application.Current.Host.Source.AbsoluteUri.LastIndexOf(
" / " ));
    
// 初始化设置图片链接数组
    imageSelector.SetImages( new   string []
    {
        String.Concat(baseUri, 
" /../Images/1.jpg " ),
        String.Concat(baseUri, 
" /../Images/2.jpg " ),
        String.Concat(baseUri, 
" /../Images/3.jpg " ),
        String.Concat(baseUri, 
" /../Images/4.jpg " ),
        String.Concat(baseUri, 
" /../Images/5.jpg " ),
        String.Concat(baseUri, 
" /../Images/6.jpg " ),
        String.Concat(baseUri, 
" /../Images/7.jpg " ),
        String.Concat(baseUri, 
" /../Images/8.jpg " )              
    });
}

void  OnImageSelected( object  sender, ImageSelectedEventArgs e)
{
    
// 当选择某一图片时,放大显示
    snipCanvas.Cursor  =  Cursors.Hand;
    snipCanvasFadeIn.Begin();
    snipImage.SetValue(Image.SourceProperty, e.ImageSource);
}

     
void  onExitMouseUp( object  sender, MouseButtonEventArgs e)
{ 
    
// 当点击关闭时
    snipCanvasFadeOut.Begin();
}

   上面代码中的OnImageSelected用于单击某张图片时放大显示,如下图:
 
 

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

     tag:silverlight,imageselector,imagesnipper

     作者:代震军,daizhj

     原文链接:[url]http://www.cnblogs.com/daizhj/archive/2008/09/10/1288315.html[/url]

     源码下载,请 点击这里:)

本文出自 “代震军:http://t.sina..” 博客,转载请与作者联系!

你可能感兴趣的:(职场,silverlight,休闲,imageselector,ImageSnipper)