C
C#2y ago
Indeed

❔ 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
3 Replies
Indeed
Indeed2y ago
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;
}
}
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;
}
}
//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);
}
//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);
}
______ 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;
}
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;
element.Loaded -= LoadedHandler;
element.Loaded += LoadedHandler;
since in static context we cannot see whether we are subscribed or not _______ 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>
<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>
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;
}
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
Shinyshark2y ago
Items that are invisible or disabled will not participate in events. What are you trying to do specifically? I use a recursive method to find a parent for something in WPF
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.