Merge branch 'master' into deprecate-radial
This commit is contained in:
Коммит
72bcb6b884
|
@ -11,7 +11,7 @@
|
|||
<Grid Margin="40"
|
||||
Background="White">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<Grid Height="3000">
|
||||
<Grid Height="6000">
|
||||
<Border Width="200"
|
||||
Height="200"
|
||||
HorizontalAlignment="Center"
|
||||
|
@ -35,7 +35,8 @@
|
|||
VerticalAlignment="Top"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Click="CloseButton_Click">
|
||||
Click="CloseButton_Click"
|
||||
Foreground="Black">
|
||||
<SymbolIcon Symbol="Cancel" />
|
||||
</Button>
|
||||
</Grid>
|
||||
|
|
|
@ -82,16 +82,19 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
|
|||
|
||||
if (lazyLoadingControlHost != null)
|
||||
{
|
||||
lazyLoadingControlHost.Child = imageExLazyLoadingControl;
|
||||
// Allow this to act as a toggle.
|
||||
if (lazyLoadingControlHost.Child == null)
|
||||
{
|
||||
lazyLoadingControlHost.Child = imageExLazyLoadingControl;
|
||||
}
|
||||
else
|
||||
{
|
||||
lazyLoadingControlHost.Child = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
SampleController.Current.RegisterNewCommand("Clear image cache", async (sender, args) =>
|
||||
{
|
||||
container?.Children?.Clear();
|
||||
GC.Collect(); // Force GC to free file locks
|
||||
await ImageCache.Instance.ClearAsync();
|
||||
});
|
||||
SampleController.Current.RegisterNewCommand("Remove images", (sender, args) => container?.Children?.Clear());
|
||||
|
||||
await LoadDataAsync();
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Toolkit.Uwp.UI.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of caching to be applied to <see cref="ImageEx"/>.
|
||||
/// Default is <see cref="Custom"/>
|
||||
/// </summary>
|
||||
public enum ImageExCachingStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// Caching is handled by <see cref="ImageEx"/>'s custom caching system.
|
||||
/// </summary>
|
||||
Custom,
|
||||
|
||||
/// <summary>
|
||||
/// Caching is handled internally by UWP.
|
||||
/// </summary>
|
||||
Internal
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ using Windows.Media.Casting;
|
|||
using Windows.UI.Composition;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
||||
namespace Microsoft.Toolkit.Uwp.UI.Controls
|
||||
{
|
||||
|
@ -33,7 +34,12 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// <inheritdoc/>
|
||||
public override CompositionBrush GetAlphaMask()
|
||||
{
|
||||
return IsInitialized ? (Image as Image).GetAlphaMask() : null;
|
||||
if (IsInitialized && Image is Image image)
|
||||
{
|
||||
return image.GetAlphaMask();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -42,7 +48,12 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// <returns>The image as a <see cref="CastingSource"/>.</returns>
|
||||
public CastingSource GetAsCastingSource()
|
||||
{
|
||||
return IsInitialized ? (Image as Image).GetAsCastingSource() : null;
|
||||
if (IsInitialized && Image is Image image)
|
||||
{
|
||||
return image.GetAsCastingSource();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,11 +40,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// </summary>
|
||||
public static readonly DependencyProperty IsCacheEnabledProperty = DependencyProperty.Register(nameof(IsCacheEnabled), typeof(bool), typeof(ImageExBase), new PropertyMetadata(false));
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="CachingStrategy"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty CachingStrategyProperty = DependencyProperty.Register(nameof(CachingStrategy), typeof(ImageExCachingStrategy), typeof(ImageExBase), new PropertyMetadata(ImageExCachingStrategy.Custom));
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="EnableLazyLoading"/> dependency property.
|
||||
/// </summary>
|
||||
|
@ -126,15 +121,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
set { SetValue(IsCacheEnabledProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating how the <see cref="ImageEx"/> will be cached.
|
||||
/// </summary>
|
||||
public ImageExCachingStrategy CachingStrategy
|
||||
{
|
||||
get { return (ImageExCachingStrategy)GetValue(CachingStrategyProperty); }
|
||||
set { SetValue(CachingStrategyProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether gets or sets is lazy loading enable. (17763 or higher supported)
|
||||
/// </summary>
|
||||
|
|
|
@ -24,9 +24,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// </summary>
|
||||
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(nameof(Source), typeof(object), typeof(ImageExBase), new PropertyMetadata(null, SourceChanged));
|
||||
|
||||
private Uri _uri;
|
||||
private bool _isHttpSource;
|
||||
private CancellationTokenSource _tokenSource = null;
|
||||
//// Used to track if we get a new request, so we can cancel any potential custom cache loading.
|
||||
private CancellationTokenSource _tokenSource;
|
||||
|
||||
private object _lazyLoadingSource;
|
||||
|
||||
/// <summary>
|
||||
|
@ -66,19 +66,28 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
return uri.IsAbsoluteUri && (uri.Scheme == "http" || uri.Scheme == "https");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method to call to assign an <see cref="ImageSource"/> value to the underlying <see cref="Image"/> powering <see cref="ImageExBase"/>.
|
||||
/// </summary>
|
||||
/// <param name="source"><see cref="ImageSource"/> to assign to the image.</param>
|
||||
private void AttachSource(ImageSource source)
|
||||
{
|
||||
var image = Image as Image;
|
||||
var brush = Image as ImageBrush;
|
||||
|
||||
if (image != null)
|
||||
// Setting the source at this point should call ImageExOpened/VisualStateManager.GoToState
|
||||
// as we register to both the ImageOpened/ImageFailed events of the underlying control.
|
||||
// We only need to call those methods if we fail in other cases before we get here.
|
||||
if (Image is Image image)
|
||||
{
|
||||
image.Source = source;
|
||||
}
|
||||
else if (brush != null)
|
||||
else if (Image is ImageBrush brush)
|
||||
{
|
||||
brush.ImageSource = source;
|
||||
}
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
VisualStateManager.GoToState(this, UnloadedState, true);
|
||||
}
|
||||
}
|
||||
|
||||
private async void SetSource(object source)
|
||||
|
@ -88,15 +97,14 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
return;
|
||||
}
|
||||
|
||||
this._tokenSource?.Cancel();
|
||||
_tokenSource?.Cancel();
|
||||
|
||||
this._tokenSource = new CancellationTokenSource();
|
||||
_tokenSource = new CancellationTokenSource();
|
||||
|
||||
AttachSource(null);
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
VisualStateManager.GoToState(this, UnloadedState, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -107,106 +115,29 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
{
|
||||
AttachSource(imageSource);
|
||||
|
||||
ImageExOpened?.Invoke(this, new ImageExOpenedEventArgs());
|
||||
VisualStateManager.GoToState(this, LoadedState, true);
|
||||
return;
|
||||
}
|
||||
|
||||
_uri = source as Uri;
|
||||
if (_uri == null)
|
||||
var uri = source as Uri;
|
||||
if (uri == null)
|
||||
{
|
||||
var url = source as string ?? source.ToString();
|
||||
if (!Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out _uri))
|
||||
if (!Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out uri))
|
||||
{
|
||||
ImageExFailed?.Invoke(this, new ImageExFailedEventArgs(new UriFormatException("Invalid uri specified.")));
|
||||
VisualStateManager.GoToState(this, FailedState, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_isHttpSource = IsHttpUri(_uri);
|
||||
if (!_isHttpSource && !_uri.IsAbsoluteUri)
|
||||
if (!IsHttpUri(uri) && !uri.IsAbsoluteUri)
|
||||
{
|
||||
_uri = new Uri("ms-appx:///" + _uri.OriginalString.TrimStart('/'));
|
||||
uri = new Uri("ms-appx:///" + uri.OriginalString.TrimStart('/'));
|
||||
}
|
||||
|
||||
await LoadImageAsync(_uri);
|
||||
}
|
||||
|
||||
private async Task LoadImageAsync(Uri imageUri)
|
||||
{
|
||||
if (_uri != null)
|
||||
{
|
||||
if (IsCacheEnabled)
|
||||
{
|
||||
switch (CachingStrategy)
|
||||
{
|
||||
case ImageExCachingStrategy.Custom when _isHttpSource:
|
||||
await SetHttpSourceCustomCached(imageUri);
|
||||
break;
|
||||
case ImageExCachingStrategy.Custom:
|
||||
case ImageExCachingStrategy.Internal:
|
||||
default:
|
||||
AttachSource(new BitmapImage(imageUri));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (string.Equals(_uri.Scheme, "data", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var source = _uri.OriginalString;
|
||||
const string base64Head = "base64,";
|
||||
var index = source.IndexOf(base64Head);
|
||||
if (index >= 0)
|
||||
{
|
||||
var bytes = Convert.FromBase64String(source.Substring(index + base64Head.Length));
|
||||
var bitmap = new BitmapImage();
|
||||
AttachSource(bitmap);
|
||||
await bitmap.SetSourceAsync(new MemoryStream(bytes).AsRandomAccessStream());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AttachSource(new BitmapImage(_uri)
|
||||
{
|
||||
CreateOptions = BitmapCreateOptions.IgnoreImageCache
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SetHttpSourceCustomCached(Uri imageUri)
|
||||
{
|
||||
try
|
||||
{
|
||||
var propValues = new List<KeyValuePair<string, object>>();
|
||||
|
||||
if (DecodePixelHeight > 0)
|
||||
{
|
||||
propValues.Add(new KeyValuePair<string, object>(nameof(DecodePixelHeight), DecodePixelHeight));
|
||||
}
|
||||
|
||||
if (DecodePixelWidth > 0)
|
||||
{
|
||||
propValues.Add(new KeyValuePair<string, object>(nameof(DecodePixelWidth), DecodePixelWidth));
|
||||
}
|
||||
|
||||
if (propValues.Count > 0)
|
||||
{
|
||||
propValues.Add(new KeyValuePair<string, object>(nameof(DecodePixelType), DecodePixelType));
|
||||
}
|
||||
|
||||
var img = await ImageCache.Instance.GetFromCacheAsync(imageUri, true, _tokenSource.Token, propValues);
|
||||
|
||||
lock (LockObj)
|
||||
{
|
||||
// If you have many imageEx in a virtualized ListView for instance
|
||||
// controls will be recycled and the uri will change while waiting for the previous one to load
|
||||
if (_uri == imageUri)
|
||||
{
|
||||
AttachSource(img);
|
||||
ImageExOpened?.Invoke(this, new ImageExOpenedEventArgs());
|
||||
VisualStateManager.GoToState(this, LoadedState, true);
|
||||
}
|
||||
}
|
||||
await LoadImageAsync(uri, _tokenSource.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
@ -214,15 +145,91 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
lock (LockObj)
|
||||
ImageExFailed?.Invoke(this, new ImageExFailedEventArgs(e));
|
||||
VisualStateManager.GoToState(this, FailedState, true);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadImageAsync(Uri imageUri, CancellationToken token)
|
||||
{
|
||||
if (imageUri != null)
|
||||
{
|
||||
if (IsCacheEnabled)
|
||||
{
|
||||
if (_uri == imageUri)
|
||||
var img = await ProvideCachedResourceAsync(imageUri, token);
|
||||
|
||||
if (!_tokenSource.IsCancellationRequested)
|
||||
{
|
||||
ImageExFailed?.Invoke(this, new ImageExFailedEventArgs(e));
|
||||
VisualStateManager.GoToState(this, FailedState, true);
|
||||
// Only attach our image if we still have a valid request.
|
||||
AttachSource(img);
|
||||
}
|
||||
}
|
||||
else if (string.Equals(imageUri.Scheme, "data", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var source = imageUri.OriginalString;
|
||||
const string base64Head = "base64,";
|
||||
var index = source.IndexOf(base64Head);
|
||||
if (index >= 0)
|
||||
{
|
||||
var bytes = Convert.FromBase64String(source.Substring(index + base64Head.Length));
|
||||
var bitmap = new BitmapImage();
|
||||
await bitmap.SetSourceAsync(new MemoryStream(bytes).AsRandomAccessStream());
|
||||
|
||||
if (!_tokenSource.IsCancellationRequested)
|
||||
{
|
||||
AttachSource(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AttachSource(new BitmapImage(imageUri)
|
||||
{
|
||||
CreateOptions = BitmapCreateOptions.IgnoreImageCache
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is provided in case a developer would like their own custom caching strategy for <see cref="ImageExBase"/>.
|
||||
/// By default it uses the built-in UWP cache provided by <see cref="BitmapImage"/> and
|
||||
/// the <see cref="Image"/> control itself. This method should return an <see cref="ImageSource"/>
|
||||
/// value of the image specified by the provided uri parameter.
|
||||
/// A <see cref="CancellationToken"/> is provided in case the current request is invalidated
|
||||
/// (e.g. the container is recycled before the original image is loaded).
|
||||
/// The Toolkit also has an image cache helper which can be used as well:
|
||||
/// <see cref="CacheBase{T}.GetFromCacheAsync(Uri, bool, CancellationToken, List{KeyValuePair{string, object}})"/> in <see cref="ImageCache"/>.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// var propValues = new List<KeyValuePair<string, object>>();
|
||||
///
|
||||
/// if (DecodePixelHeight > 0)
|
||||
/// {
|
||||
/// propValues.Add(new KeyValuePair<string, object>(nameof(DecodePixelHeight), DecodePixelHeight));
|
||||
/// }
|
||||
/// if (DecodePixelWidth > 0)
|
||||
/// {
|
||||
/// propValues.Add(new KeyValuePair<string, object>(nameof(DecodePixelWidth), DecodePixelWidth));
|
||||
/// }
|
||||
/// if (propValues.Count > 0)
|
||||
/// {
|
||||
/// propValues.Add(new KeyValuePair<string, object>(nameof(DecodePixelType), DecodePixelType));
|
||||
/// }
|
||||
///
|
||||
/// // A token is provided here as well to cancel the request to the cache,
|
||||
/// // if a new image is requested.
|
||||
/// return await ImageCache.Instance.GetFromCacheAsync(imageUri, true, token, propValues);
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <param name="imageUri"><see cref="Uri"/> of the image to load from the cache.</param>
|
||||
/// <param name="token">A <see cref="CancellationToken"/> which is used to signal when the current request is outdated.</param>
|
||||
/// <returns><see cref="Task"/></returns>
|
||||
protected virtual Task<ImageSource> ProvideCachedResourceAsync(Uri imageUri, CancellationToken token)
|
||||
{
|
||||
// By default we just use the built-in UWP image cache provided within the Image control.
|
||||
return Task.FromResult((ImageSource)new BitmapImage(imageUri));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
[TemplateVisualState(Name = UnloadedState, GroupName = CommonGroup)]
|
||||
[TemplateVisualState(Name = FailedState, GroupName = CommonGroup)]
|
||||
[TemplatePart(Name = PartImage, Type = typeof(object))]
|
||||
[TemplatePart(Name = PartProgress, Type = typeof(ProgressRing))]
|
||||
public abstract partial class ImageExBase : Control
|
||||
{
|
||||
private bool _isInViewport;
|
||||
|
@ -31,11 +30,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// </summary>
|
||||
protected const string PartImage = "Image";
|
||||
|
||||
/// <summary>
|
||||
/// ProgressRing name in template
|
||||
/// </summary>
|
||||
protected const string PartProgress = "Progress";
|
||||
|
||||
/// <summary>
|
||||
/// VisualStates name in template
|
||||
/// </summary>
|
||||
|
@ -66,22 +60,11 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// </summary>
|
||||
protected object Image { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets backing object for the ProgressRing
|
||||
/// </summary>
|
||||
protected ProgressRing Progress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets object used for lock
|
||||
/// </summary>
|
||||
protected object LockObj { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ImageExBase"/> class.
|
||||
/// </summary>
|
||||
public ImageExBase()
|
||||
{
|
||||
LockObj = new object();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -90,14 +73,11 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// <param name="handler">Routed Event Handler</param>
|
||||
protected void AttachImageOpened(RoutedEventHandler handler)
|
||||
{
|
||||
var image = Image as Image;
|
||||
var brush = Image as ImageBrush;
|
||||
|
||||
if (image != null)
|
||||
if (Image is Image image)
|
||||
{
|
||||
image.ImageOpened += handler;
|
||||
}
|
||||
else if (brush != null)
|
||||
else if (Image is ImageBrush brush)
|
||||
{
|
||||
brush.ImageOpened += handler;
|
||||
}
|
||||
|
@ -109,14 +89,11 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// <param name="handler">RoutedEventHandler</param>
|
||||
protected void RemoveImageOpened(RoutedEventHandler handler)
|
||||
{
|
||||
var image = Image as Image;
|
||||
var brush = Image as ImageBrush;
|
||||
|
||||
if (image != null)
|
||||
if (Image is Image image)
|
||||
{
|
||||
image.ImageOpened -= handler;
|
||||
}
|
||||
else if (brush != null)
|
||||
else if (Image is ImageBrush brush)
|
||||
{
|
||||
brush.ImageOpened -= handler;
|
||||
}
|
||||
|
@ -128,14 +105,11 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// <param name="handler">Exception Routed Event Handler</param>
|
||||
protected void AttachImageFailed(ExceptionRoutedEventHandler handler)
|
||||
{
|
||||
var image = Image as Image;
|
||||
var brush = Image as ImageBrush;
|
||||
|
||||
if (image != null)
|
||||
if (Image is Image image)
|
||||
{
|
||||
image.ImageFailed += handler;
|
||||
}
|
||||
else if (brush != null)
|
||||
else if (Image is ImageBrush brush)
|
||||
{
|
||||
brush.ImageFailed += handler;
|
||||
}
|
||||
|
@ -147,14 +121,11 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// <param name="handler">Exception Routed Event Handler</param>
|
||||
protected void RemoveImageFailed(ExceptionRoutedEventHandler handler)
|
||||
{
|
||||
var image = Image as Image;
|
||||
var brush = Image as ImageBrush;
|
||||
|
||||
if (image != null)
|
||||
if (Image is Image image)
|
||||
{
|
||||
image.ImageFailed -= handler;
|
||||
}
|
||||
else if (brush != null)
|
||||
else if (Image is ImageBrush brush)
|
||||
{
|
||||
brush.ImageFailed -= handler;
|
||||
}
|
||||
|
@ -169,7 +140,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
RemoveImageFailed(OnImageFailed);
|
||||
|
||||
Image = GetTemplateChild(PartImage) as object;
|
||||
Progress = GetTemplateChild(PartProgress) as ProgressRing;
|
||||
|
||||
IsInitialized = true;
|
||||
|
||||
|
@ -191,26 +161,23 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
base.OnApplyTemplate();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
var newSquareSize = Math.Min(finalSize.Width, finalSize.Height) / 8.0;
|
||||
|
||||
if (Progress?.Width == newSquareSize)
|
||||
{
|
||||
Progress.Height = newSquareSize;
|
||||
}
|
||||
|
||||
return base.ArrangeOverride(finalSize);
|
||||
}
|
||||
|
||||
private void OnImageOpened(object sender, RoutedEventArgs e)
|
||||
/// <summary>
|
||||
/// Underlying <see cref="Image.ImageOpened"/> event handler.
|
||||
/// </summary>
|
||||
/// <param name="sender">Image</param>
|
||||
/// <param name="e">Event Arguments</param>
|
||||
protected virtual void OnImageOpened(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ImageExOpened?.Invoke(this, new ImageExOpenedEventArgs());
|
||||
VisualStateManager.GoToState(this, LoadedState, true);
|
||||
}
|
||||
|
||||
private void OnImageFailed(object sender, ExceptionRoutedEventArgs e)
|
||||
/// <summary>
|
||||
/// Underlying <see cref="Image.ImageFailed"/> event handler.
|
||||
/// </summary>
|
||||
/// <param name="sender">Image</param>
|
||||
/// <param name="e">Event Arguments</param>
|
||||
protected virtual void OnImageFailed(object sender, ExceptionRoutedEventArgs e)
|
||||
{
|
||||
ImageExFailed?.Invoke(this, new ImageExFailedEventArgs(new Exception(e.ErrorMessage)));
|
||||
VisualStateManager.GoToState(this, FailedState, true);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<PackageTags>UWP Toolkit Windows Controls XAML Markdown CameraPreview Camera DropShadow ImageEx InAppNotification InfiniteCanvas Radial RadialProgressBar Scroll ScrollHeader Tile</PackageTags>
|
||||
<!-- ARM64 builds for managed apps use .NET Native. We can't use the Reflection Provider for that. -->
|
||||
<EnableTypeInfoReflection Condition="'$(Configuration)' == 'Debug'">false</EnableTypeInfoReflection>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
Загрузка…
Ссылка в новой задаче