Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
357d2ba
Wire up Unload event
XAML-Knight Aug 19, 2021
d529d48
Added FrameworkElementExtension test
XAML-Knight Aug 23, 2021
b2851d3
add test file, wip framework extension
XAML-Knight Aug 25, 2021
8c9890b
Apply WeakReference
XAML-Knight Aug 31, 2021
2f9a266
Added missing header
XAML-Knight Sep 1, 2021
c5b2bb7
Place DP props on one line
XAML-Knight Sep 3, 2021
55316d4
Remove blank line
XAML-Knight Sep 7, 2021
762818c
Add test for grid unload
XAML-Knight Sep 8, 2021
cd475a3
Apply Await
XAML-Knight Sep 8, 2021
27c302f
Aid the unload effort
XAML-Knight Sep 9, 2021
1206930
Test added to proj
XAML-Knight Sep 9, 2021
669c355
Merge remote-tracking branch 'XAML-Knight/dev/AncestorTheUnloaded' in…
XAML-Knight Sep 9, 2021
45ce6ad
Wire up Unload event
XAML-Knight Aug 19, 2021
547cc92
Added FrameworkElementExtension test
XAML-Knight Aug 23, 2021
6b049eb
add test file, wip framework extension
XAML-Knight Aug 25, 2021
a529c02
Apply WeakReference
XAML-Knight Aug 31, 2021
f35da93
Added missing header
XAML-Knight Sep 1, 2021
9b937b9
Place DP props on one line
XAML-Knight Sep 3, 2021
46e6072
Remove blank line
XAML-Knight Sep 7, 2021
eccae8a
Add test for grid unload
XAML-Knight Sep 8, 2021
82b2819
Apply Await
XAML-Knight Sep 8, 2021
f99184c
Aid the unload effort
XAML-Knight Sep 9, 2021
48e323c
Merge remote-tracking branch 'XAML-Knight/dev/AncestorTheUnloaded' in…
XAML-Knight Sep 9, 2021
afb83c5
Ignore Unit Tests to get build to pass
XAML-Knight Sep 14, 2021
70c5a8e
Set dummy variable, as check that runs after main body of test
XAML-Knight Sep 14, 2021
8396bf9
Detach from loaded, and test improvements
XAML-Knight Sep 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ public static object GetAncestor(DependencyObject obj)
/// <param name="value">FrameworkElement</param>
public static void SetAncestor(DependencyObject obj, object value)
{
obj.SetValue(AncestorProperty, value);
obj.SetValue(AncestorProperty, new WeakReference<object>(value));
}

/// <summary>
/// Attached <see cref="DependencyProperty"/> for retrieving a parent <see cref="object"/> for the <see cref="AncestorProperty"/>
/// </summary>
public static readonly DependencyProperty AncestorProperty =
DependencyProperty.RegisterAttached("Ancestor", typeof(object), typeof(FrameworkElementExtensions), new PropertyMetadata(null));
DependencyProperty.RegisterAttached("Ancestor", typeof(WeakReference<object>), typeof(FrameworkElementExtensions), new PropertyMetadata(null));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By changing the type here we break using it in XAML as intended. This can be demonstrated with the TokenizingTextBox as it uses this feature to grab the TokenSpacing property from its parent.


/// <summary>
/// Gets the Type of Ancestor to look for from this element.
Expand Down Expand Up @@ -80,6 +80,7 @@ private static void FrameworkElement_Loaded(object sender, RoutedEventArgs e)
{
if (sender is FrameworkElement fe)
{
fe.Loaded -= FrameworkElement_Loaded;
SetAncestor(fe, fe.FindAscendant(GetAncestorType(fe)));
}
}
Expand Down
108 changes: 108 additions & 0 deletions UnitTests/UnitTests.UWP/Extensions/Test_FrameworkElementExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// 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 Microsoft.Toolkit.Uwp;
using Microsoft.Toolkit.Uwp.UI;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Markup;

namespace UnitTests.Extensions
{
[TestClass]
public class Test_FrameworkElementExtensions : VisualUITestBase
{
[Ignore]
[TestCategory("FrameworkElementExtensions")]
[TestMethod]
public async Task Test_Ancestor_WeakReference()
{
// Need to sim loading the control, and not just load the XAML via XamlReader
await App.DispatcherQueue.EnqueueAsync(async () =>
{
var treeRoot = XamlReader.Load(
@"<Page
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
xmlns:controls=""using:Microsoft.Toolkit.Uwp.UI.Controls""
xmlns:ui=""using:Microsoft.Toolkit.Uwp.UI"">

<Grid x:Name=""OuterGrid"" Width=""200"" Background=""Khaki"">
<Button x:Name=""InnerButton"" ui:FrameworkElementExtensions.AncestorType=""Grid"" />
</Grid>

</Page>") as Page;

Assert.IsNotNull(treeRoot, "Could not load XAML tree.");
await SetTestContentAsync(treeRoot);

// Need to simulate loading the control (and not just rely upon XamlReader.Load)
var frame = new Frame();

await App.DispatcherQueue.EnqueueAsync(() => frame.Navigate(treeRoot.GetType()));

Assert.IsInstanceOfType(frame.Content, typeof(Page));

var btn = treeRoot.FindChild("InnerButton") as Button;

Assert.IsNull(btn.Parent);

await App.DispatcherQueue.EnqueueAsync(() => btn.SetValue(FrameworkElementExtensions.AncestorProperty, new object()));

Assert.IsNull(btn.Parent);
});
}

[Ignore]
[TestCategory("FrameworkElementExtensions")]
[TestMethod]
public async Task Test_Ancestor_WeakRef_UnloadGrid()
{
// Need to sim loading the control, and not just load the XAML via XamlReader
await App.DispatcherQueue.EnqueueAsync(async () =>
{
var placeholder = new object();

var treeRoot = XamlReader.Load(
@"<Page
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
xmlns:controls=""using:Microsoft.Toolkit.Uwp.UI.Controls""
xmlns:ui=""using:Microsoft.Toolkit.Uwp.UI"">

<Grid x:Name=""OuterGrid"" Width=""200"" Background=""Khaki"">
<Button x:Name=""InnerButton"" ui:FrameworkElementExtensions.AncestorType=""Grid"" />
</Grid>

</Page>") as Page;

Assert.IsNotNull(treeRoot, "Could not load XAML tree.");
await SetTestContentAsync(treeRoot);

// Need to simulate loading the control (and not just rely upon XamlReader.Load)
var frame = new Frame();

await App.DispatcherQueue.EnqueueAsync(() => frame.Navigate(treeRoot.GetType()));

Assert.IsInstanceOfType(frame.Content, typeof(Page));

var grid = treeRoot.FindChild("OuterGrid") as Grid;
var button = treeRoot.FindChild("InnerButton") as Button;

await App.DispatcherQueue.EnqueueAsync(() => button.SetValue(FrameworkElementExtensions.AncestorProperty, new object()));

treeRoot.Unloaded += (sender, e) =>
{
Assert.AreEqual(grid, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want to have a value set here that we check is set below after the await SetTestContent as well, otherwise if this doesn't fire then we never know, but we want to make sure it fires, eh?

};

// Allow treeRoot to Unload, before test ends
await SetTestContentAsync(null);

Assert.IsNotNull(placeholder);
});
}
}
}
1 change: 1 addition & 0 deletions UnitTests/UnitTests.UWP/UnitTests.UWP.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@
<Compile Include="Converters\Test_StringFormatConverter.cs" />
<Compile Include="Converters\Test_TypeToObjectConverter.cs" />
<Compile Include="Extensions\Helpers\ObjectWithNullableBoolProperty.cs" />
<Compile Include="Extensions\Test_FrameworkElementExtensions.cs" />
<Compile Include="Extensions\Test_StringExtensions.cs" />
<Compile Include="Extensions\Test_UIElementExtensions_Coordinates.cs" />
<Compile Include="Extensions\Test_VisualTreeExtensions.cs" />
Expand Down