Merge pull request #4404 from Ryken100/ryken100/feature-AttachedNineGridCardShadow
Clip inner content from AttachedCardShadow using CompositionMaskBrush
This commit is contained in:
Коммит
cca764fafb
|
@ -37,7 +37,8 @@
|
||||||
CornerRadius="32"
|
CornerRadius="32"
|
||||||
Color="@[Color:Brush:Black]"
|
Color="@[Color:Brush:Black]"
|
||||||
Offset="@[Offset:Vector3:4,4]"
|
Offset="@[Offset:Vector3:4,4]"
|
||||||
Opacity="@[Opacity:DoubleSlider:1.0:0.0-1.0]"/>
|
Opacity="@[Opacity:DoubleSlider:1.0:0.0-1.0]"
|
||||||
|
InnerContentClipMode="@[InnerContentClipMode:Enum:InnerContentClipMode.CompositionGeometricClip]"/>
|
||||||
</ui:Effects.Shadow>
|
</ui:Effects.Shadow>
|
||||||
</Rectangle>
|
</Rectangle>
|
||||||
<!-- If you want to apply a shadow directly in your visual tree to an untemplated element
|
<!-- If you want to apply a shadow directly in your visual tree to an untemplated element
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Toolkit.Uwp.UI.Media
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The method that each instance of <see cref="AttachedCardShadow"/> uses when clipping its inner content.
|
||||||
|
/// </summary>
|
||||||
|
public enum InnerContentClipMode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Do not clip inner content.
|
||||||
|
/// </summary>
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use <see cref="Windows.UI.Composition.CompositionMaskBrush"/> to clip inner content.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This mode has better performance than <see cref="CompositionGeometricClip"/>.
|
||||||
|
/// </remarks>
|
||||||
|
CompositionMaskBrush,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use <see cref="Windows.UI.Composition.CompositionGeometricClip"/> to clip inner content.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Content clipped in this mode will have smoother corners than when using <see cref="CompositionMaskBrush"/>.
|
||||||
|
/// </remarks>
|
||||||
|
CompositionGeometricClip
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ using Windows.Foundation;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
using Windows.UI.Composition;
|
using Windows.UI.Composition;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Hosting;
|
||||||
|
|
||||||
namespace Microsoft.Toolkit.Uwp.UI.Media
|
namespace Microsoft.Toolkit.Uwp.UI.Media
|
||||||
{
|
{
|
||||||
|
@ -20,9 +21,18 @@ namespace Microsoft.Toolkit.Uwp.UI.Media
|
||||||
public sealed class AttachedCardShadow : AttachedShadowBase
|
public sealed class AttachedCardShadow : AttachedShadowBase
|
||||||
{
|
{
|
||||||
private const float MaxBlurRadius = 72;
|
private const float MaxBlurRadius = 72;
|
||||||
private static readonly TypedResourceKey<CompositionGeometricClip> ClipResourceKey = "Clip";
|
|
||||||
|
|
||||||
|
private static readonly TypedResourceKey<CompositionGeometricClip> ClipResourceKey = "Clip";
|
||||||
private static readonly TypedResourceKey<CompositionPathGeometry> PathGeometryResourceKey = "PathGeometry";
|
private static readonly TypedResourceKey<CompositionPathGeometry> PathGeometryResourceKey = "PathGeometry";
|
||||||
|
private static readonly TypedResourceKey<CompositionMaskBrush> OpacityMaskBrushResourceKey = "OpacityMask";
|
||||||
|
private static readonly TypedResourceKey<ShapeVisual> OpacityMaskShapeVisualResourceKey = "OpacityMaskShapeVisual";
|
||||||
|
private static readonly TypedResourceKey<CompositionRoundedRectangleGeometry> OpacityMaskGeometryResourceKey = "OpacityMaskGeometry";
|
||||||
|
private static readonly TypedResourceKey<CompositionSpriteShape> OpacityMaskSpriteShapeResourceKey = "OpacityMaskSpriteShape";
|
||||||
|
private static readonly TypedResourceKey<CompositionVisualSurface> OpacityMaskShapeVisualSurfaceResourceKey = "OpacityMaskShapeVisualSurface";
|
||||||
|
private static readonly TypedResourceKey<CompositionSurfaceBrush> OpacityMaskShapeVisualSurfaceBrushResourceKey = "OpacityMaskShapeVisualSurfaceBrush";
|
||||||
|
private static readonly TypedResourceKey<CompositionVisualSurface> OpacityMaskVisualSurfaceResourceKey = "OpacityMaskVisualSurface";
|
||||||
|
private static readonly TypedResourceKey<CompositionSurfaceBrush> OpacityMaskSurfaceBrushResourceKey = "OpacityMaskSurfaceBrush";
|
||||||
|
private static readonly TypedResourceKey<SpriteVisual> OpacityMaskVisualResourceKey = "OpacityMaskVisual";
|
||||||
private static readonly TypedResourceKey<CompositionRoundedRectangleGeometry> RoundedRectangleGeometryResourceKey = "RoundedGeometry";
|
private static readonly TypedResourceKey<CompositionRoundedRectangleGeometry> RoundedRectangleGeometryResourceKey = "RoundedGeometry";
|
||||||
private static readonly TypedResourceKey<CompositionSpriteShape> ShapeResourceKey = "Shape";
|
private static readonly TypedResourceKey<CompositionSpriteShape> ShapeResourceKey = "Shape";
|
||||||
private static readonly TypedResourceKey<ShapeVisual> ShapeVisualResourceKey = "ShapeVisual";
|
private static readonly TypedResourceKey<ShapeVisual> ShapeVisualResourceKey = "ShapeVisual";
|
||||||
|
@ -39,6 +49,16 @@ namespace Microsoft.Toolkit.Uwp.UI.Media
|
||||||
typeof(AttachedCardShadow),
|
typeof(AttachedCardShadow),
|
||||||
new PropertyMetadata(4d, OnDependencyPropertyChanged)); // Default WinUI ControlCornerRadius is 4
|
new PropertyMetadata(4d, OnDependencyPropertyChanged)); // Default WinUI ControlCornerRadius is 4
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="DependencyProperty"/> for <see cref="InnerContentClipMode"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty InnerContentClipModeProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
nameof(InnerContentClipMode),
|
||||||
|
typeof(InnerContentClipMode),
|
||||||
|
typeof(AttachedCardShadow),
|
||||||
|
new PropertyMetadata(InnerContentClipMode.CompositionGeometricClip, OnDependencyPropertyChanged));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the roundness of the shadow's corners.
|
/// Gets or sets the roundness of the shadow's corners.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -48,24 +68,47 @@ namespace Microsoft.Toolkit.Uwp.UI.Media
|
||||||
set => SetValue(CornerRadiusProperty, value);
|
set => SetValue(CornerRadiusProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the mode use to clip inner content from the shadow.
|
||||||
|
/// </summary>
|
||||||
|
public InnerContentClipMode InnerContentClipMode
|
||||||
|
{
|
||||||
|
get => (InnerContentClipMode)GetValue(InnerContentClipModeProperty);
|
||||||
|
set => SetValue(InnerContentClipModeProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override bool IsSupported => SupportsCompositionVisualSurface;
|
public override bool IsSupported => SupportsCompositionVisualSurface;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected internal override bool SupportsOnSizeChangedEvent => true;
|
protected internal override bool SupportsOnSizeChangedEvent => true;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected internal override void OnElementContextInitialized(AttachedShadowElementContext context)
|
||||||
|
{
|
||||||
|
UpdateVisualOpacityMask(context);
|
||||||
|
base.OnElementContextInitialized(context);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override void OnPropertyChanged(AttachedShadowElementContext context, DependencyProperty property, object oldValue, object newValue)
|
protected override void OnPropertyChanged(AttachedShadowElementContext context, DependencyProperty property, object oldValue, object newValue)
|
||||||
{
|
{
|
||||||
if (property == CornerRadiusProperty)
|
if (property == CornerRadiusProperty)
|
||||||
{
|
{
|
||||||
|
UpdateShadowClip(context);
|
||||||
|
UpdateVisualOpacityMask(context);
|
||||||
|
|
||||||
var geometry = context.GetResource(RoundedRectangleGeometryResourceKey);
|
var geometry = context.GetResource(RoundedRectangleGeometryResourceKey);
|
||||||
if (geometry != null)
|
if (geometry != null)
|
||||||
{
|
{
|
||||||
geometry.CornerRadius = new Vector2((float)(double)newValue);
|
geometry.CornerRadius = new Vector2((float)(double)newValue);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (property == InnerContentClipModeProperty)
|
||||||
|
{
|
||||||
UpdateShadowClip(context);
|
UpdateShadowClip(context);
|
||||||
|
UpdateVisualOpacityMask(context);
|
||||||
|
SetElementChildVisual(context);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -114,6 +157,13 @@ namespace Microsoft.Toolkit.Uwp.UI.Media
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override CompositionClip GetShadowClip(AttachedShadowElementContext context)
|
protected override CompositionClip GetShadowClip(AttachedShadowElementContext context)
|
||||||
{
|
{
|
||||||
|
if (InnerContentClipMode != InnerContentClipMode.CompositionGeometricClip)
|
||||||
|
{
|
||||||
|
context.RemoveAndDisposeResource(PathGeometryResourceKey);
|
||||||
|
context.RemoveAndDisposeResource(ClipResourceKey);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// The way this shadow works without the need to project on another element is because
|
// The way this shadow works without the need to project on another element is because
|
||||||
// we're clipping the inner part of the shadow which would be cast on the element
|
// we're clipping the inner part of the shadow which would be cast on the element
|
||||||
// itself away. This method is creating an outline so that we are only showing the
|
// itself away. This method is creating an outline so that we are only showing the
|
||||||
|
@ -144,24 +194,130 @@ namespace Microsoft.Toolkit.Uwp.UI.Media
|
||||||
return clip;
|
return clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the <see cref="CompositionBrush"/> used to mask <paramref name="context"/>.<see cref="AttachedShadowElementContext.SpriteVisual">SpriteVisual</see>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">The <see cref="AttachedShadowElementContext"/> whose <see cref="SpriteVisual"/> will be masked.</param>
|
||||||
|
private void UpdateVisualOpacityMask(AttachedShadowElementContext context)
|
||||||
|
{
|
||||||
|
if (InnerContentClipMode != InnerContentClipMode.CompositionMaskBrush)
|
||||||
|
{
|
||||||
|
context.RemoveAndDisposeResource(OpacityMaskShapeVisualResourceKey);
|
||||||
|
context.RemoveAndDisposeResource(OpacityMaskGeometryResourceKey);
|
||||||
|
context.RemoveAndDisposeResource(OpacityMaskSpriteShapeResourceKey);
|
||||||
|
context.RemoveAndDisposeResource(OpacityMaskShapeVisualSurfaceResourceKey);
|
||||||
|
context.RemoveAndDisposeResource(OpacityMaskShapeVisualSurfaceBrushResourceKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create ShapeVisual, and CompositionSpriteShape with geometry, these will provide the visuals for the opacity mask.
|
||||||
|
ShapeVisual shapeVisual = context.GetResource(OpacityMaskShapeVisualResourceKey) ??
|
||||||
|
context.AddResource(OpacityMaskShapeVisualResourceKey, context.Compositor.CreateShapeVisual());
|
||||||
|
|
||||||
|
CompositionRoundedRectangleGeometry geometry = context.GetResource(OpacityMaskGeometryResourceKey) ??
|
||||||
|
context.AddResource(OpacityMaskGeometryResourceKey, context.Compositor.CreateRoundedRectangleGeometry());
|
||||||
|
CompositionSpriteShape shape = context.GetResource(OpacityMaskSpriteShapeResourceKey) ??
|
||||||
|
context.AddResource(OpacityMaskSpriteShapeResourceKey, context.Compositor.CreateSpriteShape(geometry));
|
||||||
|
|
||||||
|
// Set the attributes of the geometry, and add the CompositionSpriteShape to the ShapeVisual.
|
||||||
|
// The geometry will have a thick outline and no fill, meaning that when used as a mask,
|
||||||
|
// the shadow will only be rendered on the outer area covered by the outline, clipping out its inner portion.
|
||||||
|
geometry.Offset = new Vector2(MaxBlurRadius / 2);
|
||||||
|
geometry.CornerRadius = new Vector2((MaxBlurRadius / 2) + (float)CornerRadius);
|
||||||
|
shape.StrokeThickness = MaxBlurRadius;
|
||||||
|
shape.StrokeBrush = shape.StrokeBrush ?? context.Compositor.CreateColorBrush(Colors.Black);
|
||||||
|
|
||||||
|
if (!shapeVisual.Shapes.Contains(shape))
|
||||||
|
{
|
||||||
|
shapeVisual.Shapes.Add(shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create CompositionVisualSurface using the ShapeVisual as the source visual.
|
||||||
|
CompositionVisualSurface visualSurface = context.GetResource(OpacityMaskShapeVisualSurfaceResourceKey) ??
|
||||||
|
context.AddResource(OpacityMaskShapeVisualSurfaceResourceKey, context.Compositor.CreateVisualSurface());
|
||||||
|
visualSurface.SourceVisual = shapeVisual;
|
||||||
|
|
||||||
|
geometry.Size = new Vector2((float)context.Element.ActualWidth, (float)context.Element.ActualHeight) + new Vector2(MaxBlurRadius);
|
||||||
|
shapeVisual.Size = visualSurface.SourceSize = new Vector2((float)context.Element.ActualWidth, (float)context.Element.ActualHeight) + new Vector2(MaxBlurRadius * 2);
|
||||||
|
|
||||||
|
// Create a CompositionSurfaceBrush using the CompositionVisualSurface as the source, this essentially converts the ShapeVisual into a brush.
|
||||||
|
// This brush can then be used as a mask.
|
||||||
|
CompositionSurfaceBrush opacityMask = context.GetResource(OpacityMaskShapeVisualSurfaceBrushResourceKey) ??
|
||||||
|
context.AddResource(OpacityMaskShapeVisualSurfaceBrushResourceKey, context.Compositor.CreateSurfaceBrush());
|
||||||
|
opacityMask.Surface = visualSurface;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
protected override void SetElementChildVisual(AttachedShadowElementContext context)
|
||||||
|
{
|
||||||
|
if (context.TryGetResource(OpacityMaskShapeVisualSurfaceBrushResourceKey, out CompositionSurfaceBrush opacityMask))
|
||||||
|
{
|
||||||
|
// If the resource for OpacityMaskShapeVisualSurfaceBrushResourceKey exists it means this.InnerContentClipMode == CompositionVisualSurface,
|
||||||
|
// which means we need to take some steps to set up an opacity mask.
|
||||||
|
|
||||||
|
// Create a CompositionVisualSurface, and use the SpriteVisual containing the shadow as the source.
|
||||||
|
CompositionVisualSurface shadowVisualSurface = context.GetResource(OpacityMaskVisualSurfaceResourceKey) ??
|
||||||
|
context.AddResource(OpacityMaskVisualSurfaceResourceKey, context.Compositor.CreateVisualSurface());
|
||||||
|
shadowVisualSurface.SourceVisual = context.SpriteVisual;
|
||||||
|
context.SpriteVisual.RelativeSizeAdjustment = Vector2.Zero;
|
||||||
|
context.SpriteVisual.Size = new Vector2((float)context.Element.ActualWidth, (float)context.Element.ActualHeight);
|
||||||
|
|
||||||
|
// Adjust the offset and size of the CompositionVisualSurface to accommodate the thick outline of the shape created in UpdateVisualOpacityMask().
|
||||||
|
shadowVisualSurface.SourceOffset = new Vector2(-MaxBlurRadius);
|
||||||
|
shadowVisualSurface.SourceSize = new Vector2((float)context.Element.ActualWidth, (float)context.Element.ActualHeight) + new Vector2(MaxBlurRadius * 2);
|
||||||
|
|
||||||
|
// Create a CompositionSurfaceBrush from the CompositionVisualSurface. This allows us to render the shadow in a brush.
|
||||||
|
CompositionSurfaceBrush shadowSurfaceBrush = context.GetResource(OpacityMaskSurfaceBrushResourceKey) ??
|
||||||
|
context.AddResource(OpacityMaskSurfaceBrushResourceKey, context.Compositor.CreateSurfaceBrush());
|
||||||
|
shadowSurfaceBrush.Surface = shadowVisualSurface;
|
||||||
|
shadowSurfaceBrush.Stretch = CompositionStretch.None;
|
||||||
|
|
||||||
|
// Create a CompositionMaskBrush, using the CompositionSurfaceBrush of the shadow as the source,
|
||||||
|
// and the CompositionSurfaceBrush created in UpdateVisualOpacityMask() as the mask.
|
||||||
|
// This creates a brush that renders the shadow with its inner portion clipped out.
|
||||||
|
CompositionMaskBrush maskBrush = context.GetResource(OpacityMaskBrushResourceKey) ??
|
||||||
|
context.AddResource(OpacityMaskBrushResourceKey, context.Compositor.CreateMaskBrush());
|
||||||
|
maskBrush.Source = shadowSurfaceBrush;
|
||||||
|
maskBrush.Mask = opacityMask;
|
||||||
|
|
||||||
|
// Create a SpriteVisual and set its brush to the CompositionMaskBrush created in the previous step,
|
||||||
|
// then set it as the child of the element in the context.
|
||||||
|
SpriteVisual visual = context.GetResource(OpacityMaskVisualResourceKey) ??
|
||||||
|
context.AddResource(OpacityMaskVisualResourceKey, context.Compositor.CreateSpriteVisual());
|
||||||
|
visual.RelativeSizeAdjustment = Vector2.One;
|
||||||
|
visual.Offset = new Vector3(-MaxBlurRadius, -MaxBlurRadius, 0);
|
||||||
|
visual.Size = new Vector2(MaxBlurRadius * 2);
|
||||||
|
visual.Brush = maskBrush;
|
||||||
|
ElementCompositionPreview.SetElementChildVisual(context.Element, visual);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.SetElementChildVisual(context);
|
||||||
|
context.RemoveAndDisposeResource(OpacityMaskVisualSurfaceResourceKey);
|
||||||
|
context.RemoveAndDisposeResource(OpacityMaskSurfaceBrushResourceKey);
|
||||||
|
context.RemoveAndDisposeResource(OpacityMaskVisualResourceKey);
|
||||||
|
context.RemoveAndDisposeResource(OpacityMaskBrushResourceKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected internal override void OnSizeChanged(AttachedShadowElementContext context, Size newSize, Size previousSize)
|
protected internal override void OnSizeChanged(AttachedShadowElementContext context, Size newSize, Size previousSize)
|
||||||
{
|
{
|
||||||
var sizeAsVec2 = newSize.ToVector2();
|
Vector2 sizeAsVec2 = newSize.ToVector2();
|
||||||
|
|
||||||
var geometry = context.GetResource(RoundedRectangleGeometryResourceKey);
|
CompositionRoundedRectangleGeometry geometry = context.GetResource(RoundedRectangleGeometryResourceKey);
|
||||||
if (geometry != null)
|
if (geometry != null)
|
||||||
{
|
{
|
||||||
geometry.Size = sizeAsVec2;
|
geometry.Size = sizeAsVec2;
|
||||||
}
|
}
|
||||||
|
|
||||||
var visualSurface = context.GetResource(VisualSurfaceResourceKey);
|
CompositionVisualSurface visualSurface = context.GetResource(VisualSurfaceResourceKey);
|
||||||
if (geometry != null)
|
if (geometry != null)
|
||||||
{
|
{
|
||||||
visualSurface.SourceSize = sizeAsVec2;
|
visualSurface.SourceSize = sizeAsVec2;
|
||||||
}
|
}
|
||||||
|
|
||||||
var shapeVisual = context.GetResource(ShapeVisualResourceKey);
|
ShapeVisual shapeVisual = context.GetResource(ShapeVisualResourceKey);
|
||||||
if (geometry != null)
|
if (geometry != null)
|
||||||
{
|
{
|
||||||
shapeVisual.Size = sizeAsVec2;
|
shapeVisual.Size = sizeAsVec2;
|
||||||
|
|
|
@ -137,10 +137,13 @@ namespace Microsoft.Toolkit.Uwp.UI
|
||||||
|
|
||||||
Parent.OnElementContextUninitialized(this);
|
Parent.OnElementContextUninitialized(this);
|
||||||
|
|
||||||
SpriteVisual.Shadow = null;
|
if (SpriteVisual != null)
|
||||||
SpriteVisual.Dispose();
|
{
|
||||||
|
SpriteVisual.Shadow = null;
|
||||||
|
SpriteVisual.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
Shadow.Dispose();
|
Shadow?.Dispose();
|
||||||
|
|
||||||
ElementCompositionPreview.SetElementChildVisual(Element, null);
|
ElementCompositionPreview.SetElementChildVisual(Element, null);
|
||||||
|
|
||||||
|
@ -197,7 +200,7 @@ namespace Microsoft.Toolkit.Uwp.UI
|
||||||
/// <returns>True if the resource exists, false otherwise</returns>
|
/// <returns>True if the resource exists, false otherwise</returns>
|
||||||
public bool TryGetResource<T>(string key, out T resource)
|
public bool TryGetResource<T>(string key, out T resource)
|
||||||
{
|
{
|
||||||
if (_resources != null && _resources.TryGetValue(key, out var objResource) && objResource is T tResource)
|
if (_resources is not null && _resources.TryGetValue(key, out var objResource) && objResource is T tResource)
|
||||||
{
|
{
|
||||||
resource = tResource;
|
resource = tResource;
|
||||||
return true;
|
return true;
|
||||||
|
@ -231,7 +234,7 @@ namespace Microsoft.Toolkit.Uwp.UI
|
||||||
/// <returns>The resource that was removed, if any</returns>
|
/// <returns>The resource that was removed, if any</returns>
|
||||||
public T RemoveResource<T>(string key)
|
public T RemoveResource<T>(string key)
|
||||||
{
|
{
|
||||||
if (_resources.TryGetValue(key, out var objResource))
|
if (_resources is not null && _resources.TryGetValue(key, out var objResource))
|
||||||
{
|
{
|
||||||
_resources.Remove(key);
|
_resources.Remove(key);
|
||||||
if (objResource is T resource)
|
if (objResource is T resource)
|
||||||
|
@ -252,7 +255,7 @@ namespace Microsoft.Toolkit.Uwp.UI
|
||||||
public T RemoveAndDisposeResource<T>(string key)
|
public T RemoveAndDisposeResource<T>(string key)
|
||||||
where T : IDisposable
|
where T : IDisposable
|
||||||
{
|
{
|
||||||
if (_resources.TryGetValue(key, out var objResource))
|
if (_resources is not null && _resources.TryGetValue(key, out var objResource))
|
||||||
{
|
{
|
||||||
_resources.Remove(key);
|
_resources.Remove(key);
|
||||||
if (objResource is T resource)
|
if (objResource is T resource)
|
||||||
|
@ -306,7 +309,7 @@ namespace Microsoft.Toolkit.Uwp.UI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ClearAndDisposeResources()
|
public void ClearAndDisposeResources()
|
||||||
{
|
{
|
||||||
if (_resources != null)
|
if (_resources is not null)
|
||||||
{
|
{
|
||||||
foreach (var kvp in _resources)
|
foreach (var kvp in _resources)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче