C#
C#

help

Root Question Message

Indeed 🐸
Indeed 🐸2/3/2023
❔ WPF Cannot find child when it's there

Hi!
I am working on my own RoundedCorners attachedproperty however I have stumbled upon a problem
Problem: When an item that starts invisible goes visible the effect is not applied

I've tried experimenting with Loaded and IsVisibleChanged events, where IsVisibleChanged actually fires on the visibility change and the Loaded fires on the start
But when IsVisibleChanged fires there are still no children detected in a tree to even try to look for a border
Indeed 🐸
Indeed 🐸2/3/2023
public static class RoundedCorners {
    public static readonly DependencyProperty RadiusProperty = DependencyProperty.RegisterAttached(
        "Radius",
        typeof(CornerRadius),
        typeof(RoundedCorners),
        new PropertyMetadata(default(CornerRadius), RadiusChanged));

    public static void SetRadius(DependencyObject element, CornerRadius value) {
        element.SetValue(RadiusProperty, value);
    }

    public static CornerRadius GetRadius(DependencyObject element) {
        return (CornerRadius)element.GetValue(RadiusProperty);
    }

    public static void RadiusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        Border? border = d as Border;
        if (border == null) {
            border = UIHelper.FindChild<Border>(d);
        }

        if (border == null) {
            InitialRadiusSet(d, e);
            return;
        }

        border.CornerRadius = (CornerRadius)e.NewValue;
    }

    private static void InitialRadiusSet(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        var element = d as Control;
        if (element == null) return;

        element.Loaded -= LoadedHandler;
        element.Loaded += LoadedHandler;
    }

    private static void LoadedHandler(object sender, RoutedEventArgs e) {
        var element = sender as Control;
        if (element == null) return;

        var border = UIHelper.FindChild<Border>(element);
        if (border == null) return;

        var radius = GetRadius(element);
        border.CornerRadius = radius;
    }
}
Indeed 🐸
Indeed 🐸2/3/2023
    //one of few sample dependency properties 
    public static readonly DependencyProperty TopLeftProperty = DependencyProperty.RegisterAttached(
      "TopLeft",
      typeof(double),
      typeof(RoundedCorners),
      new PropertyMetadata(default(double), TopLeftChanged));

    public static void SetTopLeft(DependencyObject element, double value) {
        element.SetValue(TopLeftProperty, value);
    }

    public static double GetTopLeft(DependencyObject element) {
        return (double)element.GetValue(TopLeftProperty);
    }

    private static void TopLeftChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        var cornerRadius = GetRadius(d);
        cornerRadius.TopLeft = (double)e.NewValue;
        SetRadius(d, cornerRadius);
    }
Indeed 🐸
Indeed 🐸2/3/2023
______
this code handles initial loading in items and then reloading them

    private static void InitialRadiusSet(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        var element = d as Control;
        if (element == null) return;

        element.Loaded -= LoadedHandler;
        element.Loaded += LoadedHandler;
    }

    private static void LoadedHandler(object sender, RoutedEventArgs e) {
        var element = sender as Control;
        if (element == null) return;

        var border = UIHelper.FindChild<Border>(element);
        if (border == null) return;

        var radius = GetRadius(element);
        border.CornerRadius = radius;
    }


        element.Loaded -= LoadedHandler;
        element.Loaded += LoadedHandler;

since in static context we cannot see whether we are subscribed or not
Indeed 🐸
Indeed 🐸2/3/2023
_______
offending code:

                        <Button
                            Width="40"
                            Height="40"
                            Margin="10"
                            attached:RoundedCorners.Radius="{StaticResource RoundedSmRadius}"
                            Background="{StaticResource BrushBgOverlay}"
                            BorderThickness="0"
                            Command="{Binding ConfirmTitleCommand}">
                            <Button.Style>
                                <Style TargetType="{x:Type Button}">
                                    <Style.Triggers>
                                        <Trigger Property="IsEnabled" Value="False">
                                            <Setter Property="Visibility" Value="Collapsed" />
                                        </Trigger>
                                    </Style.Triggers>
                                </Style>
                            </Button.Style>
                        </Button>
Indeed 🐸
Indeed 🐸2/3/2023
    public static T? FindChild<T>(DependencyObject parent)
       where T : DependencyObject {
        if (parent == null) return null;
        T? foundChild = null;

        int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < childrenCount; i++) {
            var child = VisualTreeHelper.GetChild(parent, i);
            T? childType = child as T;
            if (childType != null) {
                foundChild = (T)child;
                break;
            }

            foundChild = FindChild<T>(child);
            if (foundChild != null) break;

        }

        return foundChild;
    }


child finding method mentioned up
Shinyshark
Shinyshark2/3/2023
Items that are invisible or disabled will not participate in events.
Shinyshark
Shinyshark2/3/2023
What are you trying to do specifically?
Shinyshark
Shinyshark2/3/2023
I use a recursive method to find a parent for something in WPF
ContactFrequently Asked QuestionsJoin The DiscordBugs & Feature RequestsTerms & Privacy