зеркало из https://github.com/DeGsoft/maui-linux.git
146 строки
3.5 KiB
C#
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;
|
|
}
|
|
}
|