Silverlight 图片相册控件






4.80/5 (4投票s)
带有缩放和幻灯片功能的 Silverlight 图片相册控件。
引言
在我其中一个 Silverlight 项目中,需求是显示在线图片的幻灯片播放,并且需要实现缩放功能。我使用 Silverlight 工具中提供的 'Silverlight 模板控件' 在 Silverlight 中创建了一个可重用的控件。在这里,我想分享我的相册代码,它使用 XML 文件从服务器上多个映射到相册的文件夹中显示图像。
使用代码
目标是创建一个可在 Silverlight 项目中重用的相册控件,如下所示
<grid x:name="LayoutRoot" />
<xamlalbum x:name="XAlbum" albumsrc="Album.xml"
borderthickness="1" borderbrush="Black"
disablealbumselection="True" slideduration="3"
height="500" width="600" imgsource="Babies" />
</grid />
获得如下输出
开发控件
创建一个新的 'Silverlight 类库' 项目来创建控件,并构建一个 .dll 文件以分发该控件。
添加一个类型为 'Silverlight 模板控件' 的新控件以创建我们的控件
这将为控件的代码隐藏创建一个类文件,以及 Theme 文件夹下的 Generic.xml 文件,其中包含我们控件的模板。
以下是包含下一页和上一页按钮以及用于幻灯片播放和文件夹选择的其他按钮的模板代码。有一个滑块控件用于缩放控件。鼠标滚轮事件也已添加到图像上以进行缩放。
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SLNuke">
<Style TargetType="local:XAMLAlbum">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:XAMLAlbum">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Canvas Name="root" Width="{TemplateBinding Width}"
local:Clip.ToBounds="True"
Height="{TemplateBinding Height}" Margin="0,0,0,0" >
<Canvas.Resources>
<Storyboard x:Name="SlideShow">
<ObjectAnimationUsingKeyFrames
BeginTime="00:00:00"
x:Name="objectSS"
Storyboard.TargetProperty="Text"
Storyboard.TargetName="txtCurrentImg">
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Style TargetType="Button"
x:Name="AlbumButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Background="White"
BorderBrush="black"
BorderThickness="2">
<Canvas Background="Transparent"
Width="20" Height="20"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock Canvas.Left="6"
Canvas.Top="3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="black"
FontFamily="Arial"
FontWeight="Bold"
FontSize="14"
Text="{TemplateBinding Content}">
</TextBlock>
</Canvas>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Button"
x:Name="SlideShowButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Background="White"
BorderBrush="black"
BorderThickness="2">
<Canvas Background="Transparent"
Width="20" Height="20"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Rectangle Canvas.Top="3"
Canvas.Left="3"
Width="14" Height="10"
Stroke="Black"
StrokeThickness="1">
</Rectangle>
<Line Stroke="Black"
StrokeThickness="1"
X1="4" Y1="17"
X2="9"
Y2="13"></Line>
<Line Stroke="Black"
StrokeThickness="1"
X1="16" Y1="17"
X2="11" Y2="13">
</Line>
</Canvas>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Button"
x:Name="SlideShowDisabledButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Background="White"
BorderBrush="black"
BorderThickness="2">
<Canvas Background="Transparent"
Width="20" Height="20"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Rectangle Canvas.Top="3"
Canvas.Left="3"
Width="14" Height="10"
Stroke="Black"
StrokeThickness="1"></Rectangle>
<Line Stroke="Black" StrokeThickness="1"
X1="4" Y1="17"
X2="9" Y2="13"></Line>
<Line Stroke="Black" StrokeThickness="1"
X1="16" Y1="17"
X2="11" Y2="13"></Line>
<Line Stroke="Red" StrokeThickness="1"
X1="6" Y1="4"
X2="13" Y2="11"></Line>
<Ellipse Canvas.Top="4"
Canvas.Left="6" Width="7"
Height="7" Stroke="Red"></Ellipse>
</Canvas>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Canvas.Resources>
<Image Canvas.Left="0"
Canvas.Top="0" Stretch="Uniform"
Source="{TemplateBinding ImgSource}"
Name="mainImg">
<Image.RenderTransform>
<ScaleTransform x:Name="ImgScaleTransform"
ScaleX="1" ScaleY="1"></ScaleTransform>
</Image.RenderTransform>
</Image>
<TextBox Name="txtCurrentImg"
Text="0" Opacity="0"></TextBox>
<Button Content=">"
Style="{StaticResource AlbumButtonStyle}"
Name="btnNext" Opacity="0.1"
Height="20" Width="20" >
</Button>
<Button Content="<"
Style="{StaticResource AlbumButtonStyle}"
Name="btnPrev" Opacity="0.1"
Height="20" Width="20">
</Button>
<Button Style="{StaticResource SlideShowDisabledButtonStyle}"
Name="btnSlideShow" Opacity="0.1"
Height="20" Width="20">
</Button>
<Slider x:Name="sldrZoom"
Orientation="Vertical" Opacity="0.2"
Height="100" Width="20"
Maximum="10" Minimum="1"
Value="1"></Slider>
<Popup Name="ablumList" IsOpen="False">
<ListBox Name="lstAlbums"
Margin="0,0,0,0" Padding="0,0,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock MinWidth="100"
Text="{Binding}" Height="15"
Foreground="Black"
FontSize="10"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Popup>
<Image Name="btnAlbums" Opacity="0.2"
Height="30" Width="30"></Image>
</Canvas>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
相册源文件 (.xml) 包含以下格式,其中包含要绑定到控件的相册(文件夹)以及将复制到使用当前控件的项目的 ClientBin 的图片文件名。
<?xml version="1.0" encoding="utf-8" ?>
<Albums>
<Album Name="Babies">
<Pic>baby1.jpg</Pic>
<Pic>baby2.jpg</Pic>
.....
</Album>
......
</Albums>
在代码隐藏 XAMLAlbum.cs 中,通过对服务器的异步调用来加载上述 XML 文件,该服务器由 AlbumSrc
属性引用以获取相册列表和图片名称。在这里,我使用 GetTemplateChild()
方法从运行时模板中获取控件
string[] arrPics;
public static readonly DependencyProperty AlbumSrcProperty =
DependencyProperty.Register("AlbumSrc",
typeof(String), typeof(XAMLAlbum), null);
public string AlbumSrc
{
get { return (string)GetValue(AlbumSrcProperty); }
set { SetValue(AlbumSrcProperty, value); }
}
/// <summary>
/// Override the apply template handler.
/// </summary>
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
....
SetFirstPicToImage();
}
public int CurrentImg
{
get { return (int)GetValue(CurrentImgProperty); }
set
{
SetValue(CurrentImgProperty, value);
ShowPicture();
}
}
void SetFirstPicToImage()
{
WebClient wc = new WebClient();
wc.OpenReadCompleted += wc_OpenReadCompleted;
wc.OpenReadAsync(new Uri(AlbumSrc, UriKind.Relative));
}
XDocument doc;
private void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error != null)
{
return;
}
using (Stream s = e.Result)
{
//load the xml file
doc = XDocument.Load(s);
//get the current folder name to show that is
//given by the user in the property ImgSourceProperty
strFolder = (string)GetValue(ImgSourceProperty);
var pics = from p in doc.Descendants("Album")
where (string)p.Attribute("Name") == strFolder
select p;
var pic = from p in pics.Descendants("Pic")
select (string)p;
arrPics = new string[pic.Count()];
int ind = 0;
foreach (string str in pic.ToArray())
{
arrPics[ind] = str;
ind++;
}
// this will call method ShowPicture() through
// the property setter - 0 to show the first picture from album
CurrentImg = 0;
//load album names to listbox
if (GetTemplateChild("lstAlbums") != null)
{
ListBox lst = ((ListBox)GetTemplateChild("lstAlbums"));
var albums = from p in doc.Descendants("Album")
select (string)p.Attribute("Name");
lst.ItemsSource = albums.ToList();
lst.SelectedIndex = 0;
Canvas root = ((Canvas)GetTemplateChild("root"));
Popup albumList = ((Popup)GetTemplateChild("ablumList"));
double left = 3;
albumList.SetValue(Canvas.LeftProperty, left);
double top = root.Height - albums.Count() * 15 - 56;
albumList.SetValue(Canvas.TopProperty, top);
albumList.MouseLeftButtonUp +=
new MouseButtonEventHandler(albumList_MouseLeftButtonUp);
lst.SelectionChanged +=
new SelectionChangedEventHandler(lst_SelectionChanged);
}
}
}
void ShowPicture()
{
if (arrPics.Length == 0) return;
if (CurrentImg < 0)
{
CurrentImg = 0;
return;
}
if (CurrentImg > arrPics.Length - 1)
{
CurrentImg = arrPics.Length - 1;
return;
}
ImageSourceConverter objImgSrc = new ImageSourceConverter();
((Image)GetTemplateChild("mainImg")).SetValue(Image.SourceProperty,
objImgSrc.ConvertFromString(strFolder + "/" + arrPics[CurrentImg]));
}
构建项目以获取 DLL 文件。
在 Silverlight 应用程序中使用控件
创建一个新的 Silverlight 项目,并添加对控件 DLL 的引用。该控件可以像下面这样添加到页面中
<UserControl xmlns:my="clr-namespace:SLNuke;assembly=SLNuke"
x:Class="SLNukeTest.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:DesignWidth="640"
d:DesignHeight="480">
<Grid x:Name="LayoutRoot">
<my:XAMLAlbum ImgSource="Babies"
Width="600" Height="500" x:Name="XAlbum"
SlideDuration="3" DisableAlbumSelection="True"
BorderBrush="Black" BorderThickness="1"
AlbumSrc="Album.xml" ></my:XAMLAlbum>
</Grid>
</UserControl>
创建一个具有上述格式的 Album.xml 文件并复制到项目的 ClientBin 中。并将图片复制到与 XML 文件中写入的相册名称相同的文件夹中,并将它们放在 ClientBin 下(请注意,我只复制了相册 Babies 和 Flowers 的图片;Nature 将不会显示,因为图片在附加项目文件 SLNukeTest 中不可用)。
关注点
控件可以缩放和播放幻灯片。当屏幕上图像的宽度和高度减小时,缩放功能非常有用,此时图片清晰度不会受到影响。相册可以设置为仅一个文件夹,并且属性 DisableAlbumSelection
可以设置为 true
,以使控件仅显示一个文件夹的图片,并且文件夹选择按钮将被隐藏。