Skip to content

Commit b6ec0bc

Browse files
Merge pull request #4230 from michael-hawker/shadow-events
Fix #4214 - Update AttachedDropShadow visual on layout/visibility
2 parents 8d7f8c2 + fb5b405 commit b6ec0bc

File tree

2 files changed

+70
-4
lines changed

2 files changed

+70
-4
lines changed

Microsoft.Toolkit.Uwp.UI/Shadows/AttachedDropShadow.cs

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System;
56
using System.Linq;
67
using System.Numerics;
78
using Windows.Foundation;
@@ -166,6 +167,16 @@ protected internal override void OnElementContextUninitialized(AttachedShadowEle
166167
_container.Children.Remove(context.SpriteVisual);
167168
}
168169

170+
context.SpriteVisual?.StopAnimation("Size");
171+
172+
context.Element.LayoutUpdated -= Element_LayoutUpdated;
173+
174+
if (context.VisibilityToken != null)
175+
{
176+
context.Element.UnregisterPropertyChangedCallback(UIElement.VisibilityProperty, context.VisibilityToken.Value);
177+
context.VisibilityToken = null;
178+
}
179+
169180
base.OnElementContextUninitialized(context);
170181
}
171182

@@ -176,6 +187,50 @@ protected override void SetElementChildVisual(AttachedShadowElementContext conte
176187
{
177188
_container.Children.InsertAtTop(context.SpriteVisual);
178189
}
190+
191+
// Handles size changing and other elements around it updating.
192+
context.Element.LayoutUpdated -= Element_LayoutUpdated;
193+
context.Element.LayoutUpdated += Element_LayoutUpdated;
194+
195+
if (context.VisibilityToken != null)
196+
{
197+
context.Element.UnregisterPropertyChangedCallback(UIElement.VisibilityProperty, context.VisibilityToken.Value);
198+
context.VisibilityToken = null;
199+
}
200+
201+
context.VisibilityToken = context.Element.RegisterPropertyChangedCallback(UIElement.VisibilityProperty, Element_VisibilityChanged);
202+
}
203+
204+
private void Element_LayoutUpdated(object sender, object e)
205+
{
206+
// Update other shadows to account for layout changes
207+
CastToElement_SizeChanged(null, null);
208+
}
209+
210+
private void Element_VisibilityChanged(DependencyObject sender, DependencyProperty dp)
211+
{
212+
if (sender is FrameworkElement element)
213+
{
214+
var context = GetElementContext(element);
215+
216+
if (element.Visibility == Visibility.Collapsed)
217+
{
218+
if (_container != null && _container.Children.Contains(context.SpriteVisual))
219+
{
220+
_container.Children.Remove(context.SpriteVisual);
221+
}
222+
}
223+
else
224+
{
225+
if (_container != null && !_container.Children.Contains(context.SpriteVisual))
226+
{
227+
_container.Children.InsertAtTop(context.SpriteVisual);
228+
}
229+
}
230+
}
231+
232+
// Update other shadows to account for layout changes
233+
CastToElement_SizeChanged(null, null);
179234
}
180235

181236
/// <inheritdoc/>
@@ -255,12 +310,24 @@ protected override CompositionBrush GetShadowMask(AttachedShadowElementContext c
255310
}
256311

257312
// Position our shadow in the correct spot to match the corresponding element.
258-
context.SpriteVisual.Size = context.Element.RenderSize.ToVector2();
259313
context.SpriteVisual.Offset = context.Element.CoordinatesFrom(CastTo).ToVector3();
260314

315+
BindSizeAndScale(context.SpriteVisual, context.Element);
316+
261317
return mask;
262318
}
263319

320+
private static void BindSizeAndScale(CompositionObject source, UIElement target)
321+
{
322+
var visual = ElementCompositionPreview.GetElementVisual(target);
323+
var bindSizeAnimation = source.Compositor.CreateExpressionAnimation($"{nameof(visual)}.Size * {nameof(visual)}.Scale.XY");
324+
325+
bindSizeAnimation.SetReferenceParameter(nameof(visual), visual);
326+
327+
// Start the animation
328+
source.StartAnimation("Size", bindSizeAnimation);
329+
}
330+
264331
private void CustomMaskedElement_Loaded(object sender, RoutedEventArgs e)
265332
{
266333
var context = GetElementContext(sender as FrameworkElement);
@@ -274,9 +341,6 @@ private void CustomMaskedElement_Loaded(object sender, RoutedEventArgs e)
274341
/// <inheritdoc/>
275342
protected internal override void OnSizeChanged(AttachedShadowElementContext context, Size newSize, Size previousSize)
276343
{
277-
var sizeAsVec2 = newSize.ToVector2();
278-
279-
context.SpriteVisual.Size = sizeAsVec2;
280344
context.SpriteVisual.Offset = context.Element.CoordinatesFrom(CastTo).ToVector3();
281345

282346
UpdateShadowClip(context);

Microsoft.Toolkit.Uwp.UI/Shadows/AttachedShadowElementContext.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public sealed class AttachedShadowElementContext
2020

2121
private Dictionary<string, object> _resources;
2222

23+
internal long? VisibilityToken { get; set; }
24+
2325
/// <summary>
2426
/// Gets a value indicating whether or not this <see cref="AttachedShadowElementContext"/> has been initialized.
2527
/// </summary>

0 commit comments

Comments
 (0)