zoukankan      html  css  js  c++  java
  • 【Win 10应用开发】延迟加载图片的另一种方法

    上一篇文章中老周给大伙介绍了x:Phase和x:Bind的用法,并演示了一个延迟加载的示例。不过,那个例子会遗留一个问题,就是UI线程被阻塞,所以启动应用较慢。

    如果希望图片可以延迟加载,或许我们可以动动其他想法,对了,INotifyPropertyChanged接口可以成为突破口。

    大伙伴们都知道,实现这个接口可以让类型支持属性更改通知,当属性的值被更新后,会及时更新用户界面上的显示内容。我的思路就是:在数据对象实例化时,先让其显示一张“占位”图片,即未有图片数据时显示的一张临时图片,然后再去拉取图片资源,当真正的图片资源拿到后再修改相应的属性,这样一来,UI会自动更新,用真正需要的图片替代前面显示的临时图片。

    唉,看老周上面说得很神秘的样子,没事,咱们实战一下。

    为了好演示,我就定义一个简单的类型,一个字符串类型的Name属性,和一个BitmapImage类型的Image属性,并实现INotifyPropertyChanged接口。

        public class ItemInfo : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected void OnPropertyChanged([CallerMemberName]string propName = "")
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
            }
    
            #region 私有字段
            private string m_name;
            private BitmapImage m_image;
            private static Random rand =new Random();
            #endregion
    
            public ItemInfo(string _name, Uri _imageUri)
            {
                Name = _name;
                // 初始图像
                Image = new BitmapImage(new Uri("ms-appx:///images/0.png"));
    
                Task t = LoadImageAsync(_imageUri);
            }
    
            public string Name
            {
                get { return m_name; }
                set
                {
                    if (value != m_name)
                    {
                        m_name = value;
                        OnPropertyChanged();
                    }
                }
            }
    
            public BitmapImage Image
            {
                get { return m_image; }
                set
                {
                    if (m_image != value)
                    {
                        m_image = value;
                        OnPropertyChanged();
                    }
                }
            }
    
            async Task LoadImageAsync(Uri uri)
            {
                // 模拟延迟
                await Task.Delay(rand.Next(1000,5000));
                // 更改图像
                Image = new BitmapImage(uri);
            }
        }

    在类型的构造函数中,调用LoadImageAsync方法去异步读取图片,读取成功后修改Image属性,这样也会使UI同步更新。

    如果在UI上使用Image控件来显示图片,在图片更换一瞬间,由于要重新呈现,Image会发生一次闪烁。为了让这个闪烁能变得友好一些,我就想到把Image控件封装到一个用户控件里,当图片要更改时播放一个短暂的动画,这样一来,使得这个切换过程不那么刺眼。这个用户控件的XAML如下:

        <Grid>
            <Image x:Name="img" />
            <Rectangle x:Name="r" Opacity="0" Fill="LightGray"/>
        </Grid>

    Rectangle默认把它透明,不会挡住后面的图像,当要切换图像时,用动画让这个Rectangle挡一下后面的图片,这样会有一个瞬间的过度效果。

    在代码中为这个用户控件声明一个依赖项属性,并且当属性更新时也更新控件里面的Image对象。

            static DependencyProperty ImageSourceProperty = DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(UcIamgeShow), new PropertyMetadata(null, new PropertyChangedCallback(OnImageSourcePropertyChanged)));
    
            private static void OnImageSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                UcIamgeShow obj = d as UcIamgeShow;
                obj.std?.Begin();
                // 切换图片
                obj.img.Source = e.NewValue as ImageSource;
            }
    
            public ImageSource ImageSource
            {
                get { return (ImageSource)GetValue(ImageSourceProperty); }
                set { SetValue(ImageSourceProperty, value); }
            }

    使用这个用户控件时,将ImageSource属性和数据源对象进行绑定即可。比如:

       <local:UcIamgeShow Width="150" Height="150" Margin="5" ImageSource="{Binding Image,Mode=OneWay}" />

    大概原理就这样,大伙伴们可以下载示例源码自己玩耍。

    看看最终的效果,可否满意。

    示例源代码下载

  • 相关阅读:
    543. Diameter of Binary Tree
    1519. Number of Nodes in the Sub-Tree With the Same Label
    WinCMD CMDKEY
    Delphi TDataSet
    Delphi DBGrid 实现多选和获取多选的值
    Access 错误: Data type mismatch in criteria expression
    Delphi Timage 介绍和操作[1](图片判断、清空、类型)
    Delphi WinAPI CopyFile、CopyFileEx、CopyFileTransacted -复制文件
    Delphi 图片转换(jpg、bitmap、png、gif)
    WinCMD NET USE 命令
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/4981072.html
Copyright © 2011-2022 走看看