[英]Display images in UWA that is not from App Assets
我很难在UWP应用中显示图像。 我的图像位于图像库中。
问题是: 如何在UWP的Image Xaml控件中显示jpg,而不是在项目“资产”中显示jpg?
到目前为止,使用绑定
尝试将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>
雷蒙德是对的!
CurrentImage = new BitmapImage();
await CurrentImage.SetSourceAsync(await image.StorageFile.OpenAsync(FileAccessMode.Read));
雷蒙德的好东西!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.