由于工作需要,要做一个图片浏览功能,左侧显示图片,右侧显示缩略图。现将大致做法介绍下。东湖
缩略图,没别的了 ,就是一个ListBox,左侧则是用一个canvas来显示图片。
<ListBox x:Name="lst" Grid.Column="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border Focusable="False">
<Image Source="{Binding ImageSource}" Tag="{Binding ImageIndex}" Width="150" Height="150">
</Image>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
上边就是我写的listbox的xaml代码,来分析一下。
横向的滚动是否禁用看情况。
然后用一个 StackPanel来盛放将要显示的缩略图。每个子项用一个border,border中放一个image控件。
上面这个在我看来难度最大的就是DataTemplate,这个就是一个数据模板,当绑定一个对象,如类的时候,显示数据相当有用。
我这里的image绑定的就是一个SmallImageEntity类
/// <summary>
/// 缩略图实体类
/// </summary>
public class SmallImageEntity
{
/// <summary>
/// 图片
/// </summary>
public BitmapImage ImageSource { get; set; }
/// <summary>
/// 索引
/// </summary>
public int ImageIndex { get; set; }
}
右侧我放的是border中嵌入一个canvas。 然后绑定了宽度,以及长度
<Border x:Name="border" Grid.Column="0" Margin="50" BorderThickness="3" BorderBrush="Black">
<Canvas x:Name="canvas" Width="{Binding ActualWidth,ElementName=border}" Height="{Binding ActualHeight,ElementName=border}" >
</Canvas>
</Border>
zaxm大致就是以上。下面最重要的就是代码部分。
在介绍整体代码之前我要先说一个动画类 DoubleAnimation。
这是整个图片播放的核心。它有好多构造函数,我主要用的是
// 摘要:
// 初始化 System.Windows.Media.Animation.DoubleAnimation 类的新实例,它在指定的持续时间内将动画处理从指定的起始值继续到指定的目标值,并具有指定的填充行为。
//
// 参数:
// fromValue:
// 动画的起始值。
//
// toValue:
// 动画的目标值。
//
// duration:
// 动画从头到尾播放一次所花的时间长度。有关更多信息,请参见 System.Windows.Media.Animation.Timeline.Duration
// 属性。
//
// fillBehavior:
// 指定动画在不活动时的行为方式。
public DoubleAnimation(double fromValue, double toValue, Duration duration, FillBehavior fillBehavior);
整个图片我分为三部分,左边,中间,右边。
图片向左切换时,现在在中间显示的图片向左移动,进去到左边,右侧的图片向左移动切换到中间。
向右侧切换时,同理。
这三部分时大致上的概念,并不会同时显示三张图片,只是一个位置上的定义。
所以为了图片切换,我们需要定义一下四个动画实体
/// <summary>
/// 向左移动撤出
/// </summary>
private DoubleAnimation _MiddleToLeftAnimation;
/// <summary>
/// 向左移动进入
/// </summary>
private DoubleAnimation _RightToMiddelAnimation;
/// <summary>
/// 向右移动撤出
/// </summary>
private DoubleAnimation _MiddleToRightAnimation;
/// <summary>
/// 向右移动进入
/// </summary>
private DoubleAnimation _LeftToMiddleAnimation;
看着名字应该就知道动画代表的含义,这里就不一一解释。
double i = this.canvas.ActualWidth;
_MiddleToLeftAnimation = new DoubleAnimation(0, -i, new Duration(TimeSpan.FromSeconds(0.8)), FillBehavior.HoldEnd);
_RightToMiddelAnimation = new DoubleAnimation(i, 0, new Duration(TimeSpan.FromSeconds(0.8)), FillBehavior.HoldEnd);
_MiddleToLeftAnimation.Completed += _MiddleToLeftAnimation_Completed;
_RightToMiddelAnimation.Completed += _RightToMiddelAnimation_Completed;
_LeftToMiddleAnimation = new DoubleAnimation(-i, 0, new Duration(TimeSpan.FromSeconds(0.8)), FillBehavior.HoldEnd);
_MiddleToRightAnimation = new DoubleAnimation(0, i, new Duration(TimeSpan.FromSeconds(0.8)), FillBehavior.HoldEnd);
_LeftToMiddleAnimation.Completed += _LeftToMiddleAnimation_Completed;
_MiddleToRightAnimation.Completed += _MiddleToRightAnimation_Completed;
定义动画类的具体属性,然后注册完成事件。
以第一个为例。
中间向左动画,从0,开始,负的canvas结束,持续0.8秒,结束时保持不动。 FillBehavior.HoldEnd,表示动画结束时保持不动。还有一个属性 FillBehavior.Stop,表示动画结束时还原。
然后注册一个动画结束事件是为了在动画结束后将上一张向左移动的图片删除。
整体c#代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication23
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
/// <summary>
/// 图片列表
/// </summary>
List<SmallImageEntity> ImageList = new List<SmallImageEntity>();
/// <summary>
/// 向左移动撤出
/// </summary>
private DoubleAnimation _MiddleToLeftAnimation;
/// <summary>
/// 向左移动进入
/// </summary>
private DoubleAnimation _RightToMiddelAnimation;
/// <summary>
/// 向右移动撤出
/// </summary>
private DoubleAnimation _MiddleToRightAnimation;
/// <summary>
/// 向右移动进入
/// </summary>
private DoubleAnimation _LeftToMiddleAnimation;
/// <summary>
/// 当前显示的图片
/// </summary>
int CurrentIndex = 0;
/// <summary>
/// 动画是否完成
/// </summary>
bool AnimationCompleted = false;
public MainWindow()
{
InitializeComponent();
ImageList.Add(new SmallImageEntity() { ImageSource = new BitmapImage(new Uri("1.png", UriKind.RelativeOrAbsolute)) });
ImageList.Add(new SmallImageEntity() { ImageSource = new BitmapImage(new Uri("2.png", UriKind.RelativeOrAbsolute)) });
ImageList.Add(new SmallImageEntity() { ImageSource = new BitmapImage(new Uri("3.png", UriKind.RelativeOrAbsolute)) });
ImageList.Add(new SmallImageEntity() { ImageSource = new BitmapImage(new Uri("4.jpg", UriKind.RelativeOrAbsolute)) });
this.lst.ItemsSource = ImageList;
this.Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Image image = new Image();
image.Width = this.canvas.ActualWidth;
image.Height = this.canvas.ActualHeight;
image.Source = ImageList[0].ImageSource;
canvas.Children.Add(image);
double i = this.canvas.ActualWidth;
_MiddleToLeftAnimation = new DoubleAnimation(0, -i, new Duration(TimeSpan.FromSeconds(0.8)), FillBehavior.Stop);
_RightToMiddelAnimation = new DoubleAnimation(i, 0, new Duration(TimeSpan.FromSeconds(0.8)), FillBehavior.HoldEnd);
_MiddleToLeftAnimation.Completed += _MiddleToLeftAnimation_Completed;
_RightToMiddelAnimation.Completed += _RightToMiddelAnimation_Completed;
_LeftToMiddleAnimation = new DoubleAnimation(-i, 0, new Duration(TimeSpan.FromSeconds(0.8)), FillBehavior.HoldEnd);
_MiddleToRightAnimation = new DoubleAnimation(0, i, new Duration(TimeSpan.FromSeconds(0.8)), FillBehavior.HoldEnd);
_LeftToMiddleAnimation.Completed += _LeftToMiddleAnimation_Completed;
_MiddleToRightAnimation.Completed += _MiddleToRightAnimation_Completed;
this.lst.SelectionChanged += lst_SelectionChanged;
}
void _MiddleToRightAnimation_Completed(object sender, EventArgs e)
{
if (this.canvas != null && canvas.Children.Count > 1)
{
this.canvas.Children.RemoveAt(0);
}
}
void _LeftToMiddleAnimation_Completed(object sender, EventArgs e)
{
if (this.canvas != null && canvas.Children.Count > 1)
{
this.canvas.Children.RemoveAt(0);
}
AnimationCompleted = false;
}
void _MiddleToLeftAnimation_Completed(object sender, EventArgs e)
{
if (this.canvas != null && canvas.Children.Count > 1)
{
this.canvas.Children.RemoveAt(0);
}
}
//动画结束,删除第一张
void _RightToMiddelAnimation_Completed(object sender, EventArgs e)
{
if (this.canvas != null && canvas.Children.Count > 1)
{
this.canvas.Children.RemoveAt(0);
}
AnimationCompleted = false;
}
///右侧选择时,左侧进行相应的改变
void lst_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int t_index = this.lst.SelectedIndex;
Image image = new Image();
image.Width = this.canvas.ActualWidth;
image.Height = this.canvas.ActualHeight;
image.Source = ImageList[t_index].ImageSource;
if (t_index > CurrentIndex)
{
MoveToLeftAnimate(image, t_index);
}
else if (t_index < CurrentIndex)
{
MoveToRightAnimate(image, t_index);
}
}
private void MoveToLeftAnimate(Image image, int t_index)
{
if (!AnimationCompleted)
{
CurrentIndex = t_index;
AnimationCompleted = true;
canvas.Children.Add(image);
canvas.Children[0].BeginAnimation(Canvas.LeftProperty, _MiddleToLeftAnimation);
canvas.Children[1].BeginAnimation(Canvas.LeftProperty, _RightToMiddelAnimation);
}
else
{
this.lst.SelectedItem = this.lst.Items[CurrentIndex];
// this.lst.SelectedIndex = CurrentIndex;
}
}
private void MoveToRightAnimate(Image image, int t_index)
{
if (!AnimationCompleted)
{
CurrentIndex = t_index;
AnimationCompleted = true;
canvas.Children.Add(image);
canvas.Children[0].BeginAnimation(Canvas.LeftProperty, _MiddleToRightAnimation);
canvas.Children[1].BeginAnimation(Canvas.LeftProperty, _LeftToMiddleAnimation);
}
else
{
this.lst.SelectedItem = this.lst.Items[CurrentIndex];
// this.lst.SelectedIndex = CurrentIndex;
}
}
}
/// <summary>
/// 缩略图实体类
/// </summary>
public class SmallImageEntity
{
/// <summary>
/// 图片
/// </summary>
public BitmapImage ImageSource { get; set; }
/// <summary>
/// 索引
/// </summary>
public int ImageIndex { get; set; }
}
}
//zaml代码如下
<Window x:Class="WpfApplication23.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" WindowState="Maximized">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Border x:Name="border" Grid.Column="0" Margin="50" BorderThickness="3" BorderBrush="Black">
<Canvas x:Name="canvas" Width="{Binding ActualWidth,ElementName=border}" Height="{Binding ActualHeight,ElementName=border}" >
</Canvas>
</Border>
<ListBox x:Name="lst" Grid.Column="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border Focusable="False">
<Image Source="{Binding ImageSource}" Tag="{Binding ImageIndex}" Width="150" Height="150">
</Image>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>