maui-linux/System.Maui.Platform.UAP/ImageRenderer.cs

146 строки
3.5 KiB
C#

using System;
using System.ComponentModel;
using System.Threading.Tasks;
using global::Windows.UI.Xaml;
using System.Maui.Internals;
namespace System.Maui.Platform.UWP
{
public class ImageRenderer : ViewRenderer<Image, global::Windows.UI.Xaml.Controls.Image>, IImageVisualElementRenderer
{
bool _measured;
bool _disposed;
public ImageRenderer() : base()
{
ImageElementManager.Init(this);
global::Windows.UI.Xaml.Application.Current.Resuming += OnResumingAsync;
}
bool IImageVisualElementRenderer.IsDisposed => _disposed;
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
{
if (Control.Source == null)
return new SizeRequest();
_measured = true;
return new SizeRequest(Control.Source.GetImageSourceSize());
}
protected override void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
_disposed = true;
if (disposing)
{
ImageElementManager.Dispose(this);
if (Control != null)
{
Control.ImageOpened -= OnImageOpened;
Control.ImageFailed -= OnImageFailed;
global::Windows.UI.Xaml.Application.Current.Resuming -= OnResumingAsync;
}
}
base.Dispose(disposing);
}
protected override async void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
if (Control == null)
{
var image = new global::Windows.UI.Xaml.Controls.Image();
image.ImageOpened += OnImageOpened;
image.ImageFailed += OnImageFailed;
SetNativeControl(image);
}
await TryUpdateSource().ConfigureAwait(false);
}
}
protected override async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Image.SourceProperty.PropertyName)
await TryUpdateSource().ConfigureAwait(false);
}
void OnImageOpened(object sender, RoutedEventArgs routedEventArgs)
{
if (_measured)
{
ImageElementManager.RefreshImage(this);
}
Element?.SetIsLoading(false);
}
protected virtual void OnImageFailed(object sender, ExceptionRoutedEventArgs exceptionRoutedEventArgs)
{
Log.Warning("Image Loading", $"Image failed to load: {exceptionRoutedEventArgs.ErrorMessage}");
Element?.SetIsLoading(false);
}
protected virtual async Task TryUpdateSource()
{
// By default we'll just catch and log any exceptions thrown by UpdateSource so we don't bring down
// the application; a custom renderer can override this method and handle exceptions from
// UpdateSource differently if it wants to
try
{
await UpdateSource().ConfigureAwait(false);
}
catch (Exception ex)
{
Log.Warning(nameof(ImageRenderer), "Error loading image: {0}", ex);
}
finally
{
((IImageController)Element)?.SetIsLoading(false);
}
}
protected async Task UpdateSource()
{
await ImageElementManager.UpdateSource(this).ConfigureAwait(false);
}
async void OnResumingAsync(object sender, object e)
{
try
{
await ImageElementManager.UpdateSource(this);
}
catch (Exception exception)
{
Log.Warning("Update image source after app resume",
$"ImageSource failed to update after app resume: {exception.Message}");
}
}
void IImageVisualElementRenderer.SetImage(global::Windows.UI.Xaml.Media.ImageSource image)
{
Control.Source = image;
}
global::Windows.UI.Xaml.Controls.Image IImageVisualElementRenderer.GetImage() => Control;
}
}