Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Visual|Logical]Tree extensions revamp #3685

Merged
29 commits merged into from
Feb 22, 2021

Conversation

Sergio0694
Copy link
Member

@Sergio0694 Sergio0694 commented Jan 22, 2021

Closes #3487

PR Type

What kind of change does this PR introduce?

  • Feature

Overview

There are some inconsistencies in the visual tree extensions mentioned in the linked issue, and some missing features.
This PR applies the changes mentioned in #3487 (comment).

APIs breakdown

VisualTree (click to expand):
namespace Microsoft.Toolkit.Uwp.UI.Extensions
{
    public static class VisualTree
    {
        static FrameworkElement? FindDescendant(this DependencyObject element, string name, StringComparison comparisonType = StringComparison.Ordinal);
        static T? FindDescendant<T>(this DependencyObject element) where T : notnull, DependencyObject;
        static DependencyObject? FindDescendant(this DependencyObject element, Type type);
        static T? FindDescendant<T>(this DependencyObject element, Func<T, bool> predicate) where T : notnull, DependencyObject;
        static T? FindDescendant<T, TState>(this DependencyObject element, TState state, Func<T, TState, bool> predicate) where T : notnull, DependencyObject;
        static FrameworkElement? FindDescendantOrSelf(this DependencyObject element, string name, StringComparison comparisonType = StringComparison.Ordinal);
        static T? FindDescendantOrSelf<T>(this DependencyObject element) where T : notnull, DependencyObject;
        static DependencyObject? FindDescendantOrSelf(this DependencyObject element, Type type);
        static T? FindDescendantOrSelf<T>(this DependencyObject element, Func<T, bool> predicate) where T : notnull, DependencyObject;
        static T? FindDescendantOrSelf<T, TState>(this DependencyObject element, TState state, Func<T, TState, bool> predicate) where T : notnull, DependencyObject;

        static IEnumerable<DependencyObject> FindDescendants(this DependencyObject element);

        static FrameworkElement? FindAscendant(this DependencyObject element, string name, StringComparison comparisonType = StringComparison.Ordinal);
        static T? FindAscendant<T>(this DependencyObject element) where T : notnull, DependencyObject;
        static DependencyObject? FindAscendant(this DependencyObject element, Type type);
        static T? FindAscendant<T>(this DependencyObject element, Func<T, bool> predicate) where T : notnull, DependencyObject;
        static T? FindAscendant<T, TState>(this DependencyObject element, TState state, Func<T, TState, bool> predicate) where T : notnull, DependencyObject;
        static FrameworkElement? FindAscendantOrSelf(this DependencyObject element, string name, StringComparison comparisonType = StringComparison.Ordinal);
        static T? FindAscendantOrSelf<T>(this DependencyObject element) where T : notnull, DependencyObject;
        static DependencyObject? FindAscendantOrSelf(this DependencyObject element, Type type);
        static T? FindAscendantOrSelf<T>(this DependencyObject element, Func<T, bool> predicate) where T : notnull, DependencyObject;
        static T? FindAscendantOrSelf<T, TState>(this DependencyObject element, TState state, Func<T, TState, bool> predicate) where T : notnull, DependencyObject;

        static IEnumerable<DependencyObject> FindAscendants(this DependencyObject element);
    }
}
LogicalTree (click to expand):
namespace Microsoft.Toolkit.Uwp.UI.Extensions
{
    public static class LogicalTree
    {
        static FrameworkElement? FindChild(this FrameworkElement element, string name, StringComparison comparisonType = StringComparison.Ordinal);
        static T? FindChild<T>(this FrameworkElement element) where T : notnull, FrameworkElement;
        static FrameworkElement? FindChild(this FrameworkElement element, Type type);
        static T? FindChild<T>(this FrameworkElement element, Func<T, bool> predicate) where T : notnull, FrameworkElement;
        static T? FindChild<T, TState>(this FrameworkElement element, TState state, Func<T, TState, bool> predicate) where T : notnull, FrameworkElement;
        static FrameworkElement? FindChildOrSelf(this FrameworkElement element, string name, StringComparison comparisonType = StringComparison.Ordinal);
        static T? FindChildOrSelf<T>(this FrameworkElement element) where T : notnull, FrameworkElement;
        static FrameworkElement? FindChildOrSelf(this FrameworkElement element, Type type);
        static T? FindChildOrSelf<T>(this FrameworkElement element, Func<T, bool> predicate) where T : notnull, FrameworkElement;
        static T? FindChildOrSelf<T, TState>(this FrameworkElement element, TState state, Func<T, TState, bool> predicate) where T : notnull, FrameworkElement;

        static IEnumerable<FrameworkElement> FindChildren(this FrameworkElement element);

        static FrameworkElement? FindParent(this FrameworkElement element, string name, StringComparison comparisonType = StringComparison.Ordinal);
        static T? FindParent<T>(this FrameworkElement element) where T : notnull, FrameworkElement;
        static FrameworkElement? FindParent(this FrameworkElement element, Type type);
        static T? FindParent<T>(this FrameworkElement element, Func<T, bool> predicate) where T : notnull, FrameworkElement;
        static T? FindParent<T, TState>(this FrameworkElement element, TState state, Func<T, TState, bool> predicate) where T : notnull, FrameworkElement;
        static FrameworkElement? FindParentOrSelf(this FrameworkElement element, string name, StringComparison comparisonType = StringComparison.Ordinal);
        static T? FindParentOrSelf<T>(this FrameworkElement element) where T : notnull, FrameworkElement;
        static FrameworkElement? FindParentOrSelf(this FrameworkElement element, Type type);
        static T? FindParentOrSelf<T>(this FrameworkElement element, Func<T, bool> predicate) where T : notnull, FrameworkElement;
        static T? FindParentOrSelf<T, TState>(this FrameworkElement element, TState state, Func<T, TState, bool> predicate) where T : notnull, FrameworkElement;

        static IEnumerable<FrameworkElement> FindParents(this FrameworkElement element);
        
        static UIElement? TryGetContentControl(this FrameworkElement element);
        static object? TryFindResource(this FrameworkElement element, object resourceKey);
    }
}

PR Checklist

Please check if your PR fulfills the following requirements:

  • Tested code with current supported SDKs
  • Pull Request has been submitted to the documentation repository instructions. Link:
  • Sample in sample app has been added / updated (for bug fixes / features)
  • New major technical changes in the toolkit have or will be added to the Wiki e.g. build changes, source generators, testing infrastructure, sample creation changes, etc...
  • Tests for the changes have been added (for bug fixes / features) (if applicable)
  • Header has been added to all new source files (run build/UpdateHeaders.bat)
  • Contains NO breaking changes

Other information

Opening as draft, missing updated/revamped unit tests.

@ghost
Copy link

ghost commented Jan 22, 2021

Thanks Sergio0694 for opening a Pull Request! The reviewers will test the PR and highlight if there is any conflict or changes required. If the PR is approved we will proceed to merge the pull request 🙌

@ghost ghost added the bug 🐛 An unexpected issue that highlights incorrect behavior label Jan 22, 2021
@Sergio0694 Sergio0694 removed the bug 🐛 An unexpected issue that highlights incorrect behavior label Jan 22, 2021
@Sergio0694 Sergio0694 marked this pull request as ready for review February 1, 2021 13:22
@Sergio0694
Copy link
Member Author

Sergio0694 commented Feb 1, 2021

Switching to ready for review as the PR is up to date and all tests are passing on my end after the changes to the visual/logical tree helpers. We can always add more specific tests here later, either directly to master or to another PR based off of this one 🙂

@Sergio0694 Sergio0694 force-pushed the improvements/tree-extensions branch from 6c8f1ff to 7a8a287 Compare February 8, 2021 19:22
@michael-hawker michael-hawker added the next preview ✈️ Label for marking what we want to include in the next preview release for developers to try. label Feb 8, 2021
@Sergio0694 Sergio0694 force-pushed the improvements/tree-extensions branch from 7a8a287 to f5c2f22 Compare February 9, 2021 00:34
@michael-hawker
Copy link
Member

Started adding Unit Tests for original versions here to help us test the refactor, but hitting a deadlock after the test completes successfully. ☹

@azchohfi any tips on async ninjitsu? There's three levels of TaskCompletionSource currently, so not sure if there's funky stuff going on there or something else. Something definitely seems fishy there with how it's trying to set completions in things which I would have expected to be completed already. Did find this blog as a resource too, but doesn't seem like quiet the same scenario...

Copy link
Contributor

@Rosuavio Rosuavio left a comment

Choose a reason for hiding this comment

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

Love the API changes @Sergio0694. It has me looking for excuses to use it XD

@Sergio0694
Copy link
Member Author

@RosarioPulella That's great to hear, thanks! Really happy you like these changes! 🥳

@michael-hawker michael-hawker mentioned this pull request Feb 18, 2021
10 tasks
Copy link
Member

@michael-hawker michael-hawker left a comment

Choose a reason for hiding this comment

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

Yeah, I didn't lose my comments when my machine turned off. Couple of small comments, but looking really good. Almost done with the original unit tests, but we should be able to start porting them over too and adding new ones.

Microsoft.Toolkit.Uwp.UI/Extensions/Tree/LogicalTree.cs Outdated Show resolved Hide resolved
Microsoft.Toolkit.Uwp.UI/Extensions/Tree/LogicalTree.cs Outdated Show resolved Hide resolved
@Sergio0694 Sergio0694 force-pushed the improvements/tree-extensions branch from 0d7a4a4 to 3dc484c Compare February 18, 2021 21:15
This was referenced Mar 12, 2021
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto merge ⚡ extensions ⚡ improvements ✨ in progress 🚧 introduce breaking changes 💥 next preview ✈️ Label for marking what we want to include in the next preview release for developers to try.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Inconsistent behavior for [Logical|Visual]Tree extensions
3 participants