Skip to content

Commit ed42e41

Browse files
Add AttachedShadow Sample
Had to create static Attached Property location Had to convert Vector3 to string for XAML parsing Made empty strings return zerod
1 parent 72d524c commit ed42e41

File tree

7 files changed

+126
-59
lines changed

7 files changed

+126
-59
lines changed

Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,7 @@
627627
<Content Include="SamplePages\Primitives\ConstrainedBox.bind">
628628
<SubType>Designer</SubType>
629629
</Content>
630+
<Content Include="SamplePages\Shadows\AttachedShadowWin2DXaml.bind" />
630631
<Content Include="SamplePages\KeyDownTriggerBehavior\KeyDownTriggerBehaviorXaml.bind" />
631632
</ItemGroup>
632633
<ItemGroup>
@@ -1534,4 +1535,4 @@
15341535
</Target>
15351536
<!-- No-op to avoid build error when packing solution from commandline -->
15361537
<Target Name="Pack" />
1537-
</Project>
1538+
</Project>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<Page
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6+
xmlns:ui="using:Microsoft.Toolkit.Uwp.UI"
7+
xmlns:media="using:Microsoft.Toolkit.Uwp.UI.Media"
8+
mc:Ignorable="d">
9+
10+
<!-- TODO: Show using as Resource as well... -->
11+
12+
<Grid>
13+
<Button Content="Hello Shadows!" HorizontalAlignment="Center" VerticalAlignment="Center"
14+
CornerRadius="8">
15+
<ui:Shadows.Attached>
16+
<media:AttachedCardShadow BlurRadius="@[BlurRadius:DoubleSlider:8.0:0.0-10.0]"
17+
CornerRadius="8"
18+
Color="@[Color:Brush:Black]"
19+
Offset="@[Offset:Vector3:16,16]"
20+
Opacity="@[Opacity:DoubleSlider:1.0:0.0-1.0]"/>
21+
</ui:Shadows.Attached>
22+
</Button>
23+
</Grid>
24+
</Page>

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@
4949
</controls:CaseCollection>
5050
</controls:SwitchPresenter>
5151
<controls:ConstrainedBox x:Key="ConstrainedBoxControl" />
52-
<controls:DropShadowPanel x:Key="DropShadowPanel" />
52+
<media:AttachedCardShadow x:Key="AttachedShadow" />
53+
<controls:DropShadowPanel x:Key="DropShadowPanel"
54+
ui:Shadows.Attached="{StaticResource AttachedShadow}" />
5355
</Page.Resources>
5456

5557
<Grid>

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@
170170
"Type": "ScrollHeaderPage",
171171
"Subcategory": "Layout",
172172
"About": "A UI control that works as a ListView or GridView header control with quick return, sticky and fade behavior.",
173-
"CodeUrl" : "https://github.com/CommunityToolkit/WindowsCommunityToolkit/tree/main/Microsoft.Toolkit.Uwp.UI.Behaviors/Headers",
173+
"CodeUrl": "https://github.com/CommunityToolkit/WindowsCommunityToolkit/tree/main/Microsoft.Toolkit.Uwp.UI.Behaviors/Headers",
174174
"XamlCodeFile": "ScrollHeaderCode.bind",
175175
"Icon": "/SamplePages/ScrollHeader/ScrollHeader.png",
176176
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/behaviors/HeaderBehaviors.md"
@@ -185,6 +185,15 @@
185185
"Icon": "/SamplePages/GridSplitter/GridSplitter.png",
186186
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/GridSplitter.md"
187187
},
188+
{
189+
"Name": "AttachedDropShadow (Win2D)",
190+
"Subcategory": "Media",
191+
"About": "An AttachedDropShadow allows the creation of a DropShadow for any Xaml FrameworkElement in markup.",
192+
"CodeUrl": "https://github.com/CommunityToolkit/WindowsCommunityToolkit/tree/main/Microsoft.Toolkit.Uwp.UI.Media/Shadows",
193+
"XamlCodeFile": "/SamplePages/Shadows/AttachedShadowWin2DXaml.bind",
194+
"Icon": "/SamplePages/Shadows/DropShadowPanel.png",
195+
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/DropShadowPanel.md"
196+
},
188197
{
189198
"Name": "DropShadowPanel",
190199
"Subcategory": "Media",

Microsoft.Toolkit.Uwp.UI/Extensions/StringExtensions.cs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ public static class StringExtensions
2626
[Pure]
2727
public static Vector2 ToVector2(this string text)
2828
{
29-
if (text.Length > 0)
29+
if (text.Length == 0)
30+
{
31+
return Vector2.Zero;
32+
}
33+
else
3034
{
3135
// The format <x> or <x, y> is supported
3236
text = Unbracket(text);
@@ -71,7 +75,11 @@ public static Vector2 ToVector2(this string text)
7175
[Pure]
7276
public static Vector3 ToVector3(this string text)
7377
{
74-
if (text.Length > 0)
78+
if (text.Length == 0)
79+
{
80+
return Vector3.Zero;
81+
}
82+
else
7583
{
7684
text = Unbracket(text);
7785

@@ -119,7 +127,11 @@ public static Vector3 ToVector3(this string text)
119127
[Pure]
120128
public static Vector4 ToVector4(this string text)
121129
{
122-
if (text.Length > 0)
130+
if (text.Length == 0)
131+
{
132+
return Vector4.Zero;
133+
}
134+
else
123135
{
124136
text = Unbracket(text);
125137

@@ -171,7 +183,11 @@ public static Vector4 ToVector4(this string text)
171183
[Pure]
172184
public static Quaternion ToQuaternion(this string text)
173185
{
174-
if (text.Length > 0)
186+
if (text.Length == 0)
187+
{
188+
return new();
189+
}
190+
else
175191
{
176192
text = Unbracket(text);
177193

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

Lines changed: 8 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -17,50 +17,6 @@ namespace Microsoft.Toolkit.Uwp.UI
1717
/// </summary>
1818
public abstract class AttachedShadowBase : DependencyObject
1919
{
20-
/// <summary>
21-
/// Gets the shadow attached to a <see cref="FrameworkElement"/> by getting the value of the <see cref="ShadowProperty"/> property.
22-
/// </summary>
23-
/// <param name="obj">The <see cref="FrameworkElement"/> the <see cref="AttachedShadowBase"/> is attached to.</param>
24-
/// <returns>The <see cref="AttachedShadowBase"/> that is attached to the <paramref name="obj">FrameworkElement.</paramref></returns>
25-
public static AttachedShadowBase GetShadow(FrameworkElement obj)
26-
{
27-
return (AttachedShadowBase)obj.GetValue(ShadowProperty);
28-
}
29-
30-
/// <summary>
31-
/// Attaches a shadow to an element by setting the <see cref="ShadowProperty"/> property.
32-
/// </summary>
33-
/// <param name="obj">The <see cref="FrameworkElement"/> to attach the shadow to.</param>
34-
/// <param name="value">The <see cref="AttachedShadowBase"/> that will be attached to the element</param>
35-
public static void SetShadow(FrameworkElement obj, AttachedShadowBase value)
36-
{
37-
obj.SetValue(ShadowProperty, value);
38-
}
39-
40-
/// <summary>
41-
/// Backing dependency property used to attach shadows to UI elements.
42-
/// </summary>
43-
public static readonly DependencyProperty ShadowProperty =
44-
DependencyProperty.RegisterAttached("Shadow", typeof(AttachedShadowBase), typeof(AttachedShadowBase), new PropertyMetadata(null, OnShadowChanged));
45-
46-
private static void OnShadowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
47-
{
48-
if (!(d is FrameworkElement element))
49-
{
50-
return;
51-
}
52-
53-
if (e.OldValue is AttachedShadowBase oldShadow)
54-
{
55-
oldShadow.DisconnectElement(element);
56-
}
57-
58-
if (e.NewValue is AttachedShadowBase newShadow)
59-
{
60-
newShadow.ConnectElement(element);
61-
}
62-
}
63-
6420
/// <summary>
6521
/// The <see cref="DependencyProperty"/> for <see cref="BlurRadius"/>.
6622
/// </summary>
@@ -79,9 +35,9 @@ private static void OnShadowChanged(DependencyObject d, DependencyPropertyChange
7935
public static readonly DependencyProperty OffsetProperty =
8036
DependencyProperty.Register(
8137
nameof(Offset),
82-
typeof(Vector3),
38+
typeof(string), // Needs to be string as we can't convert in XAML natively from Vector3, see https://github.com/microsoft/microsoft-ui-xaml/issues/3896
8339
typeof(AttachedShadowBase),
84-
new PropertyMetadata(Vector3.Zero, OnDependencyPropertyChanged));
40+
new PropertyMetadata(string.Empty, OnDependencyPropertyChanged));
8541

8642
/// <summary>
8743
/// The <see cref="DependencyProperty"/> for <see cref="Opacity"/>
@@ -118,11 +74,11 @@ public double Opacity
11874
}
11975

12076
/// <summary>
121-
/// Gets or sets the offset of the shadow.
77+
/// Gets or sets the offset of the shadow as a string representation of a <see cref="Vector3"/>.
12278
/// </summary>
123-
public Vector3 Offset
79+
public string Offset
12480
{
125-
get => (Vector3)GetValue(OffsetProperty);
81+
get => (string)GetValue(OffsetProperty);
12682
set => SetValue(OffsetProperty, value);
12783
}
12884

@@ -140,7 +96,7 @@ public Color Color
14096
/// </summary>
14197
protected internal abstract bool SupportsOnSizeChangedEvent { get; }
14298

143-
private void ConnectElement(FrameworkElement element)
99+
internal void ConnectElement(FrameworkElement element)
144100
{
145101
if (!IsSupported)
146102
{
@@ -158,7 +114,7 @@ private void ConnectElement(FrameworkElement element)
158114
ShadowElementContextTable.Add(element, context);
159115
}
160116

161-
private void DisconnectElement(FrameworkElement element)
117+
internal void DisconnectElement(FrameworkElement element)
162118
{
163119
if (ShadowElementContextTable == null)
164120
{
@@ -308,7 +264,7 @@ protected virtual void OnPropertyChanged(AttachedShadowElementContext context, D
308264
}
309265
else if (property == OffsetProperty)
310266
{
311-
context.Shadow.Offset = (Vector3)newValue;
267+
context.Shadow.Offset = (Vector3)(newValue as string)?.ToVector3();
312268
}
313269
}
314270

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Windows.UI.Xaml;
6+
7+
namespace Microsoft.Toolkit.Uwp.UI
8+
{
9+
/// <summary>
10+
/// Helper class for attaching <see cref="AttachedShadowBase"/> shadows to <see cref="FrameworkElement"/>s.
11+
/// </summary>
12+
public static class Shadows
13+
{
14+
/// <summary>
15+
/// Gets the shadow attached to a <see cref="FrameworkElement"/> by getting the value of the <see cref="AttachedProperty"/> property.
16+
/// </summary>
17+
/// <param name="obj">The <see cref="FrameworkElement"/> the <see cref="AttachedShadowBase"/> is attached to.</param>
18+
/// <returns>The <see cref="AttachedShadowBase"/> that is attached to the <paramref name="obj">FrameworkElement.</paramref></returns>
19+
public static AttachedShadowBase GetAttached(FrameworkElement obj)
20+
{
21+
return (AttachedShadowBase)obj.GetValue(AttachedProperty);
22+
}
23+
24+
/// <summary>
25+
/// Attaches a shadow to an element by setting the <see cref="AttachedProperty"/> property.
26+
/// </summary>
27+
/// <param name="obj">The <see cref="FrameworkElement"/> to attach the shadow to.</param>
28+
/// <param name="value">The <see cref="AttachedShadowBase"/> that will be attached to the element</param>
29+
public static void SetAttached(FrameworkElement obj, AttachedShadowBase value)
30+
{
31+
obj.SetValue(AttachedProperty, value);
32+
}
33+
34+
/// <summary>
35+
/// Attached <see cref="DependencyProperty"/> for setting an <see cref="AttachedShadowBase"/> to a <see cref="FrameworkElement"/>.
36+
/// </summary>
37+
public static readonly DependencyProperty AttachedProperty =
38+
DependencyProperty.RegisterAttached("Attached", typeof(AttachedShadowBase), typeof(Shadows), new PropertyMetadata(null, OnShadowChanged));
39+
40+
private static void OnShadowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
41+
{
42+
if (!(d is FrameworkElement element))
43+
{
44+
return;
45+
}
46+
47+
if (e.OldValue is AttachedShadowBase oldShadow)
48+
{
49+
oldShadow.DisconnectElement(element);
50+
}
51+
52+
if (e.NewValue is AttachedShadowBase newShadow)
53+
{
54+
newShadow.ConnectElement(element);
55+
}
56+
}
57+
58+
}
59+
}

0 commit comments

Comments
 (0)