在UWA中显示非来自App Assets的图像

时间:2018-04-05 16:38:45

标签: c# image uwp visual-studio-2017

我在UWP应用程序中尝试显示图像时遇到了一些困难。 我的图片位于图片库中。

问题是: 如何在UWP上的Image Xaml控件中显示jpg,这不在项目“Assets”中?

到目前为止使用Binding,我已

  • 尝试将Image.Source设置为完整路径但没有成功,图像控制仍为空白。 (用于文件访问限制的猜测)

  • 尝试将BitMapImage设置为Image.Source属性但没有成功,图像控件保持空白。 (用于文件访问限制的猜测)

  • 尝试将FileStorage类分配给Image.Source属性但没有成功,图像控件保持空白。

  • 尝试在流中加载图像文件并在BitmapImage中加载流,但是我遇到了线程问题。更多关于此的内容。

关于线程问题,我现在讨论两个问题。 加载文件/流时:

var file = File.ReadAllBytes(_currentImagePath);

我得到了

System.InvalidOperationException:'不应在UI线程上执行同步操作。考虑在Task.Run中包装此方法。'

当以任何方式使用Task.Run时,我在尝试设置位图源时会出现异常

该应用程序调用了一个为不同线程编组的接口。 (来自HRESULT的异常:0x8001010E(RPC_E_WRONG_THREAD))

var bitmap = new BitmapImage();
return await Task.Run(async () =>
{
   var file = File.ReadAllBytes(_currentImagePath);
   using (var stream = new InMemoryRandomAccessStream())
   {
       await stream.WriteAsync(file.AsBuffer());
       stream.Seek(0);
       await bitmap.SetSourceAsync(stream); // **Exception here**
       return bitmap;
    }
});

这里是完整的源代码:

namespace App1.Images
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices.WindowsRuntime;
    using System.Threading.Tasks;
    using Windows.Storage;
    using Windows.Storage.Streams;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Media.Imaging;
    using App1.Annotations;


    public class ImagesLibrairies : INotifyPropertyChanged
    {
        private readonly HashSet<Image> _images;
        private readonly string _fileTypes;
        private readonly HashSet<Image> _preferrednessFiles;
        private readonly DispatcherTimer _timer;

        private ulong _minFileSize = 5 * 1024; // 5k in bytes
        private ulong _maxFileSize = 1024 * 1024 * 20; //20 MBytes 
        private int _imageIndex = 0;

        public ImagesLibrairies()
        {
            _preferrednessFiles = new HashSet<Image>();
            _fileTypes = "*.jpg;*.jpeg;*.bmp;*.tif"; // ignore *.ico;*.png;*.svg;*.gif
            _images = new HashSet<Image>();

            _timer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 5) };
            _timer.Tick += _timer_Tick;
        }

        private Uri _currentImage;
        public Uri CurrentImage
        {
            get => _currentImage;
            private set
            {
                _currentImage = value;
                OnPropertyChanged(nameof(CurrentImage));
                OnPropertyChanged(nameof(Image));
            }
        }

        public async Task<BitmapImage> GetBitmapImage()
        {

            var bitmap = new BitmapImage();
            return await Task.Run(async () =>
              {
                  var file = File.ReadAllBytes(_currentImagePath);
                  using (var stream = new InMemoryRandomAccessStream())
                  {
                      await stream.WriteAsync(file.AsBuffer());
                      stream.Seek(0);
                      await bitmap.SetSourceAsync(stream);
                      return bitmap;
                  }
              });

        }

        public BitmapImage Image
        {
            get
            {
                if (!string.IsNullOrEmpty(_currentImagePath))
                    return GetBitmapImage().Result;

                return null;

            }
        }

        private string _currentImagePath;
        public string CurrentImagePath
        {
            get => _currentImagePath;
            set
            {
                _currentImagePath = value;
                OnPropertyChanged(nameof(CurrentImagePath));

                CurrentImage = new Uri(value);
            }
        }

        public object CurrentStorageFile { get; set; }

        private void _timer_Tick(object sender, object e)
        {
            SetNext();
        }

        public async Task ScanLibrairies()
        {

            var picturesFolder = KnownFolders.PicturesLibrary;

            var files = await picturesFolder.GetFilesAsync();

            foreach (var file in files)
            {

                Debug.WriteLine(file.Name + ", " + file.DateCreated);

                if (_images.Count >= int.MaxValue)
                    return;

                var prop = await file.GetBasicPropertiesAsync();

                var imageLocation = new Image
                {
                    StorageFile = file,
                    Properties = prop
                };

                if (imageLocation.Properties.Size < _minFileSize || imageLocation.Properties.Size > _maxFileSize)
                    continue;

                if (_preferrednessFiles.Any(o => o.Equals(imageLocation) && o.Preferredness == Preferredness.No))
                    continue;

                _images.Add(imageLocation);

            }
        }

        public void SetNext()
        {
            if (_images == null || !_images.Any())
            {
                return;
            }

            _imageIndex++;

            var image = _images.Skip(_imageIndex).FirstOrDefault();
            if (image != null)
            {
                Debug.WriteLine($"Displaying: {image.StorageFile.Path}");
            }

            CurrentImagePath = image?.StorageFile.Path;
            CurrentImage = new Uri(CurrentImagePath);
        }

        public void SetPrevious()
        {
            if (_images == null || !_images.Any())
                return;

            _imageIndex--;
            var image = _images.Skip(_imageIndex).FirstOrDefault();
            CurrentImagePath = image?.StorageFile.Path;


        }

        public void LikeThisPicture(Image picture)
        {
            var pic = _preferrednessFiles.FirstOrDefault(o => o.Equals(picture));
            if (pic == null)
            {
                picture.Preferredness = Preferredness.Very;
                _preferrednessFiles.Add(picture);
                return;
            }

            pic.Preferredness = Preferredness.Very;
        }

        public void DislikeThisPicture(Image picture)
        {
            var pic = _preferrednessFiles.FirstOrDefault(o => o.Equals(picture));
            if (pic == null)
            {
                picture.Preferredness = Preferredness.No;
                _preferrednessFiles.Add(picture);
                return;
            }

            pic.Preferredness = Preferredness.No;
        }

        public void StartAsync()
        {
            ScanLibrairies();
            _timer.Start();

        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

这里是xaml标记

<Page.DataContext>
    <images:ImagesLibrairies/>
</Page.DataContext>

<Grid >
    <!--Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">-->

    <Image Stretch="UniformToFill"  Margin="15">
        <Image.Source>
            <BitmapImage UriSource="{Binding Image}"></BitmapImage>
            <!--<BitmapImage UriSource="{Binding CurrentImagePath}"></BitmapImage>-->
            <!--<BitmapImage UriSource="D:\Utilisateurs\hugod\OneDrive\Images\jouets\20180106_132041.jpg"></BitmapImage>-->
            <!--<BitmapImage UriSource="Assets/Black-And-White-Wall-Brick-Texture-Shadow-WallpapersByte-com-3840x2160.jpg"></BitmapImage>-->
            <!--<BitmapImage UriSource="{Binding CurrentStorageFile}"></BitmapImage>-->
        </Image.Source>
    </Image>


</Grid>

1 个答案:

答案 0 :(得分:0)

雷蒙德是对的!

CurrentImage = new BitmapImage();
await CurrentImage.SetSourceAsync(await image.StorageFile.OpenAsync(FileAccessMode.Read));

雷蒙德的好东西!