由於工作需要,要做一個圖片瀏覽功能,左側顯示圖片,右側顯示縮略圖。現將大致做法介紹下。東湖
縮略圖,沒別的了 ,就是一個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>