支持GIF动画图片播放的图片控件,GIF图片源GIFSource AnimatedGIF : Image { DependencyProperty GIFSourceProperty = DependencyProperty.Register( , typeof(string), typeof(AnimatedGIF), new PropertyMetadata(OnSourcePropertyChanged)); GIF图片源,支持相对路径、绝对路径 GIFSource { get { return (string)GetValue(GIFSourceProperty); } set { SetValue(GIFSourceProperty, value); } } BitmapSource BitmapSource; FrameUpdatedEventHandler(); Delete local bitmap resource (VS.85).aspx /// </summary> [DllImport(, CharSet = CharSet.Auto, SetLastError = true)] DeleteObject(IntPtr hObject); OnInitialized(EventArgs e) { base.OnInitialized(e); this.Loaded += AnimatedGIF_Loaded; this.Unloaded += AnimatedGIF_Unloaded; } void AnimatedGIF_Unloaded(object sender, RoutedEventArgs e) { this.StopAnimate(); } void AnimatedGIF_Loaded(object sender, RoutedEventArgs e) { BindSource(this); } Start animation StartAnimate() { ImageAnimator.Animate(Bitmap, OnFrameChanged); } Stop animation StopAnimate() { ImageAnimator.StopAnimate(Bitmap, OnFrameChanged); } Event handler for the frame changed OnFrameChanged(object sender, EventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, new FrameUpdatedEventHandler(FrameUpdatedCallback)); } private void FrameUpdatedCallback() { ImageAnimator.UpdateFrames(); if (BitmapSource != null) BitmapSource.Freeze(); // Convert the bitmap to BitmapSource that can be display in WPF Visual Tree BitmapSource = GetBitmapSource(this.Bitmap, this.BitmapSource); Source = BitmapSource; InvalidateVisual(); } 属性更改处理事件 OnSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) { AnimatedGIF gif = sender as AnimatedGIF; if (gif == null) return; if (!gif.IsLoaded) return; BindSource(gif); } BindSource(AnimatedGIF gif) { gif.StopAnimate(); if (gif.Bitmap != null) gif.Bitmap.Dispose(); var path = gif.GIFSource; if (path.IsInvalid()) return; if (!Path.IsPathRooted(path)) { path = File.GetPhysicalPath(path); } gif.Bitmap = new Bitmap(path); gif.BitmapSource = GetBitmapSource(gif.Bitmap, gif.BitmapSource); gif.StartAnimate(); } private static BitmapSource GetBitmapSource(Bitmap bmap, BitmapSource bimg) { IntPtr handle = IntPtr.Zero; try { handle = bmap.GetHbitmap(); bimg = Imaging.CreateBitmapSourceFromHBitmap( handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } finally { if (handle != IntPtr.Zero) DeleteObject(handle); } return bimg; } }
View Code
五.图片列表样式,支持大数据量的虚拟化
先看看效果图(gif图,有点大):
用的是ListView作为列表容器,因为Listview支持灵活的扩展,为了实现上面的效果,集合容器ItemsPanel只能使用WrapPanel,样式本身并不复杂:
BorderBrushD:\Doc\Resource ItemTemplate VirtualizingStackPanel.IsVirtualizing CanVerticallyScroll