• WPF中,使用LISTVIEW显示图片列表,含异步显示方法


    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    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.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Windows.Threading;
    
    namespace LibraryControls
    {
        /// <summary>
        /// ImageListView.xaml 的交互逻辑
        /// </summary>
        public partial class ImageListView_M : ListView
        {
            private BackgroundWorker loadLocalBackgroudworker = null;//后台处理线程
    
            public ObservableCollection<ListBindData> bindItems = null;// 绑定的资源元素集合
    
            #region Event
            public delegate void Image_LoadDelegate(ListBindData model);
            /// <summary>
            ///图片加载事件
            /// </summary>
            public event Image_LoadDelegate Image_LoadEvent;
            public delegate void Image_MouseDownDelegate(object sender, MouseButtonEventArgs e);
            /// <summary>
            /// 鼠标在图片上按下事件
            /// </summary>
            public event Image_MouseDownDelegate Image_MouseDownEvent;
            public delegate void Image_MouseMoveDelegate(object sender, MouseEventArgs e);
            /// <summary>
            /// 鼠标在图片上移动事件
            /// </summary>
            public event Image_MouseMoveDelegate Image_MouseMoveEvent;
            public delegate void Image_MouseUpDelegate(object sender, MouseButtonEventArgs e);
            /// <summary>
            /// 鼠标在图片上松开事件
            /// </summary>
            public event Image_MouseUpDelegate Image_MouseUpEvent;
            #endregion
    
    
            private int nameLargeLength;//可展示的图片名称字数
            public int NameLargeLength
            {
                get
                {
                    return nameLargeLength;
                }
    
                set
                {
                    nameLargeLength = value;
                }
            }
    
            private string itemSourcePath;//图片路径
            public string ItemSourcePath
            {
                get
                {
                    return itemSourcePath;
                }
    
                set
                {
                    itemSourcePath = value;
                    LoadLocalImageData();
                }
            }
    
            public ImageListView_M()
            {
                InitializeComponent();
                //bindItems = new ObservableCollection<ListBindData>();
                //this.ItemsSource = bindItems;
            }
    
            #region 后台线程处理图片数据
            private void LoadLocalImageData()
            {
                this.ItemsSource = null;
                bindItems.Clear();
                if (loadLocalBackgroudworker != null)
                {
                    loadLocalBackgroudworker.CancelAsync();
                    loadLocalBackgroudworker.DoWork -= loadLocalBackgroudworker_DoWork;
                    loadLocalBackgroudworker.RunWorkerCompleted -= loadLocalBackgroudworker_RunWorkerCompleted;
                }
                loadLocalBackgroudworker = new BackgroundWorker();
                loadLocalBackgroudworker.WorkerSupportsCancellation = true;
                loadLocalBackgroudworker.DoWork += loadLocalBackgroudworker_DoWork;
                loadLocalBackgroudworker.RunWorkerCompleted += loadLocalBackgroudworker_RunWorkerCompleted;
                loadLocalBackgroudworker.RunWorkerAsync();
            }
            /// <summary>
            /// 逐个加载图片资源
            /// </summary>
            private void loadLocalBackgroudworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                this.ItemsSource = bindItems;
                int tempCount = bindItems.Count;
                for (int i = 0; i < bindItems.Count; i++)
                {
                    if (tempCount != bindItems.Count)
                    {
                        break;
                    }
                    LoadImageDataByBackground(bindItems[i]);
                }
            }
            /// <summary>
            /// 加载资源路径
            /// </summary>
            private void loadLocalBackgroudworker_DoWork(object sender, DoWorkEventArgs e)
            {
                try
                {
                    DirectoryInfo theFolder = new DirectoryInfo(ItemSourcePath);
                    if (!theFolder.Exists)
                        return;
    
                    string[] files = Directory.GetFiles(ItemSourcePath);
                    if (files.Length > 0)
                        Array.Sort(files);
    
                    for (int i = 0; i < files.Length; i++)
                    {
                        this.Dispatcher.Invoke(new Action(() =>
                        {
                            if (IsSupport(files[i]))
                            {
                                var tmpBindData = new ListBindData();
                                tmpBindData.ItemName = SetStringLength(GetFileNameEx(files[i]), nameLargeLength);
                                tmpBindData.PicPath = files[i];
                                tmpBindData.ItemWidth = 160;
                                tmpBindData.ItemHeight = 80;
                                bindItems.Add(tmpBindData);
                            }
                        }));
                    }
                }
                catch (Exception ex)
                {
    
                }
            }
            /// <summary>
            /// 加载资源图片线程
            /// </summary>
            private void LoadImageDataByBackground(ListBindData bindData)
            {
                BackgroundWorker loadImgWorker = new BackgroundWorker();
                loadImgWorker.DoWork += loadImgWorker_DoWork;
                loadImgWorker.RunWorkerCompleted += loadImgWorker_RunWorkerCompleted;
                loadImgWorker.WorkerSupportsCancellation = true;
                loadImgWorker.RunWorkerAsync(bindData);
            }
            /// <summary>
            /// 后台线程完成后释放所占资源
            /// </summary>
            private void loadImgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                var tempWorker = sender as BackgroundWorker;
                if (tempWorker != null)
                {
                    tempWorker.Dispose();
                    tempWorker = null;
                }
            }
            /// <summary>
            /// 更新资源图片
            /// </summary>
            private void loadImgWorker_DoWork(object sender, DoWorkEventArgs e)
            {
                var bindData = e.Argument as ListBindData;
                if (bindData != null)
                {
                    var temp = this.Dispatcher.BeginInvoke(new Action<ListBindData>((tempData) =>
                    {
                        if (tempData != null && !string.IsNullOrEmpty(tempData.PicPath))
                        {
                            BitmapImage bi = LoadBitmapSourceByPath(tempData.PicPath);
                            if (bi != null)
                            {
                                tempData.PicBitmapImage = bi;
                                if (bi.PixelWidth < tempData.ItemWidth && bi.PixelHeight < tempData.ItemHeight)
                                {
                                    tempData.StrethMethod = Stretch.None;
                                }
                                else
                                {
                                    tempData.StrethMethod = Stretch.UniformToFill;
                                }
                            }
                            bi = null;
                        }
                    }), DispatcherPriority.Background, bindData);
                }
            }
    
            #endregion
    
            #region 异步加载图片资源(解决BitmapImage无法异步加载的问题)
    
            /// <summary>
            /// 异步加载图片资源
            /// </summary>
            /// <param name="model"></param>
            public void LoadBitmapImageAsync(ListBindData model)
            {
                BackgroundWorker loadImgWorker = new BackgroundWorker();
                loadImgWorker.DoWork += LoadBitmapImage_DoWork;
                loadImgWorker.RunWorkerCompleted += loadImgWorker_RunWorkerCompleted;
                loadImgWorker.WorkerSupportsCancellation = true;
                loadImgWorker.RunWorkerAsync(model);
            }
            /// <summary>
            /// 更新资源图片
            /// </summary>
            private void LoadBitmapImage_DoWork(object sender, DoWorkEventArgs e)
            {
                var bindData = e.Argument as ListBindData;
                if (bindData != null)
                {
                    var temp = this.Dispatcher.BeginInvoke(new Action<ListBindData>((tempData) =>
                    {
                        if (Image_LoadEvent != null)
                        {
                  //根据需要,将图片的PICPATH(图片路径),转换成bitmapimage类型,由于这里有特殊需求,所以用事件代替执行 Image_LoadEvent(tempData); } }), DispatcherPriority.Background, bindData); } }
    #endregion #region 辅助方法 /// <summary> /// 设置显示的图片名称 /// </summary> private string SetStringLength(string text, int leng) { if (text.Length > leng) { text = text.Substring(0, leng) + "..."; return text; } else { return text; } } /// <summary> /// 从文件路径中获取文件名 /// </summary> private static String GetFileName(String fileName) { if (fileName == null || fileName == "") return ""; return fileName.Substring(fileName.LastIndexOf("\\") + 1); } /// <summary> /// 获得文件后缀名 /// </summary> private static String GetEndFile(String fileName) { return fileName.Substring(fileName.LastIndexOf(".") + 1); } /// <summary> /// 获得没有后缀的文件名 /// </summary> private static string GetFileNameEx(String fileName) { try { return GetFileName(fileName).Substring(0, GetFileName(fileName).LastIndexOf(GetEndFile(fileName)) - 1); } catch { return ""; } } /// <summary> /// 文件头转换 /// </summary> private enum FileExtension { JPG = 255216, GIF = 7173, PNG = 13780, SWF = 6787, RAR = 8297, ZIP = 8075, _7Z = 55122, VALIDFILE = 9999999 } /// <summary> /// 根据图源属性获取扩展名 /// </summary> private string GetBitmapExtensions(string path) { try { using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { string fileType = string.Empty; FileExtension extension; using (BinaryReader br = new System.IO.BinaryReader(fs)) { byte data = br.ReadByte(); fileType += data.ToString(); data = br.ReadByte(); fileType += data.ToString(); try { extension = (FileExtension)Enum.Parse(typeof(FileExtension), fileType); } catch { extension = FileExtension.VALIDFILE; } } return extension.ToString(); } } catch (Exception) { return FileExtension.VALIDFILE.ToString(); } } /// <summary> /// 受支持的图片格式 /// </summary> private List<string> supportedPicType = new List<string>() { "jpg", "png", "bmp", }; /// <summary> /// 判断该扩展名是否是受支持的图片类型 /// </summary> private bool IsBmpSupport(string ext) { return supportedPicType.FindAll((c) => c.Contains(ext.ToLower())).Count > 0; } /// <summary> /// 判断该图片是否受支持 /// </summary> private bool IsSupport(string path) { return IsBmpSupport(GetBitmapExtensions(path)); } /// <summary> /// 从指定路径读取图片源 /// </summary> private BitmapImage LoadBitmapSourceByPath(string path) { try { //文件不存在,返回空 if (!File.Exists(path)) { return null; } BitmapImage bi = new BitmapImage(); using (FileStream strream = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(strream)) { byte[] bytes = br.ReadBytes((int)strream.Length); bi.BeginInit(); bi.StreamSource = new MemoryStream(bytes); bi.EndInit(); } } return bi; } catch (Exception ex) { return null; } } #endregion #region Method /// <summary> /// 添加项 /// </summary> /// <param name="item"></param> public void AddItem(ListBindData item) { try { this.Dispatcher.Invoke(new Action(() => { bindItems.Add(item); })); LoadBitmapImageAsync(item); } catch (Exception ex) { } } /// <summary> /// 定位到指定位置 /// </summary> /// <param name="item"></param> public void Location(ListBindData item) { try { //信息定位到最底部 this.ScrollIntoView(item); } catch (Exception ex) { } } /// <summary> /// 绑定数据源 /// </summary> public void SetItemSource() { this.ItemsSource = bindItems; } #endregion #region 事件 private void Image_MouseDown(object sender, MouseButtonEventArgs e) { if (Image_MouseDownEvent != null) { Image_MouseDownEvent(sender, e); } } private void Image_MouseMove(object sender, MouseEventArgs e) { if (Image_MouseMoveEvent != null) { Image_MouseMoveEvent(sender, e); } } private void Image_MouseUp(object sender, MouseButtonEventArgs e) { if (Image_MouseUpEvent != null) { Image_MouseUpEvent(sender, e); } } #endregion } }

    前端代码:

    <ListView x:Class="LibraryControls.ImageListView_M"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:LibraryControls"
                 mc:Ignorable="d" SelectionMode="Single" Background="#f0f0f0"
                 ItemContainerStyle="{DynamicResource ListViewItemStyle}" 
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto">
        <ListView.Resources>
            <Style x:Key="txt_bottom" TargetType="TextBlock">
                <!--矢量图标必须要写在这里,才可以用触发器改变图标,否则改变无效-->
                <Setter Property="FontFamily" Value="/Fonts/#iconfont" />
                <Setter Property="Text" Value="&#xed1b;"/>
                <!--触发器,控制文字(矢量图标)及文字颜色-->
                <Style.Triggers>
                    <Trigger Property="Tag" Value="1">
                        <Setter Property="Foreground" Value="#FFFF33"/>
                        <Setter Property="Text" Value="&#xe8b1;"/>
                    </Trigger>
                    <Trigger Property="Tag" Value="0">
                        <Setter Property="Text" Value="&#xed1b;"/>
                        <Setter Property="Foreground" Value="#00FF00"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
            <Style x:Key="ListViewItemStyle" TargetType="{x:Type ListViewItem}">
                <Setter Property="AllowDrop" Value="True"/>
                <!--<Setter Property="Cursor" Value ="Hand"/>-->
                <!--<Setter Property="Margin" Value="5,5,5,5"/>-->
                <Setter Property="Foreground" Value="Black"/>
                <Setter Property="Background" Value="Black"/>
                <Setter Property="FontSize" Value="12"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListViewItem}">
                            <Grid x:Name="gridContent" HorizontalAlignment="Center" VerticalAlignment="Center">
                                <Grid.RowDefinitions>
                                    <RowDefinition />
                                    <RowDefinition Height="30"/>
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition  Width="100"/>
                                    <ColumnDefinition />
                                </Grid.ColumnDefinitions>
                                <!--图片边框,不要边框可以设置为0-->
                                <Border Name="picBorder" Background="White" BorderBrush="DarkGray" BorderThickness="3"
                                         Grid.ColumnSpan="2" Grid.RowSpan="2">
                                    <!--<Image Name="ItemPic" Height="{Binding PicBitmapImage}" Source="{Binding PicBitmapImage}" Stretch="{Binding StrethMethod}" VerticalAlignment="Center" HorizontalAlignment="Center"/>-->
                                    <Image Name="ItemPic" Height="{Binding ItemHeight}" Source="{Binding PicBitmapImage}" Stretch="{Binding StrethMethod}"
                                           VerticalAlignment="Center" HorizontalAlignment="Center" Tag="{Binding Index}"
                                          MouseDown="Image_MouseDown" MouseMove="Image_MouseMove" MouseUp="Image_MouseUp"/>
                                </Border>
                                <TextBlock Grid.Row="1"  FontSize="30" VerticalAlignment="Bottom" HorizontalAlignment="Left" Tag="{Binding IsDisease}" Style="{StaticResource txt_bottom}"/>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsSelected" Value="True">
                                    <Setter TargetName="picBorder" Property="BorderBrush" Value="Blue"></Setter>
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter TargetName="picBorder" Property="BorderBrush" Value="Red"></Setter>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListView.Resources>
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel>
                </WrapPanel>
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
    </ListView>

    注意事项:如果在前端代码中,imageSoruce绑定的是图片路径,则后台添加项方法(AddItem)无需使用LoadBitmapImageAsync方法;在使用异步加载listview的时候,请实现Image_LoadEvent事件,或者直接在调用Image_LoadEvent事件处理,写相关代码即可。

    参考文献:https://blog.csdn.net/weixin_43976890/article/details/99850570

  • 相关阅读:
    json和xml数据的解析
    block(闭包)
    自定义控件注意点
    字符串使用
    如何用运行时,给系统分类添加属性?
    论代码规范
    常用设计模式
    多控制器管理
    GDI+学习及代码总结之-----画笔 .
    MFC程序添加Web浏览器控件(IE控件)
  • 原文地址:https://www.cnblogs.com/chensong0524/p/16337101.html
Copyright © 2020-2023  润新知