A C# utility library providing helpful extension methods for WPF applications, focusing on visual tree navigation and manipulation.
# Package manager
Install-Package OliveStudio.WPF
# .NET CLI
dotnet add package OliveStudio.WPF- .NET Framework 4.6.1 or later
- WPF (Windows Presentation Foundation)
Extension methods for DependencyObject that simplify visual tree navigation in WPF applications.
Finds the first parent of a specified type by traversing up the visual tree.
public static TDependencyType? FindParentOfType<TDependencyType>(this DependencyObject dependencyObject)Parameters:
dependencyObject- The dependency object to start the search from
Returns:
- The first parent of the specified type, or
nullif no such parent exists
Finds all visual children of a specified type by recursively searching down the visual tree.
public static List<TDependencyType> FindVisualChildrenOfType<TDependencyType>(this DependencyObject dependencyObject)
where TDependencyType : DependencyObjectParameters:
dependencyObject- The parent dependency object to search within
Returns:
- A list of all visual children of the specified type
using OliveStudio;
// In a button click event handler
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
// Find the parent Window
var parentWindow = button.FindParentOfType<Window>();
if (parentWindow != null)
{
parentWindow.Title = "Button was clicked!";
}
// Find the parent Grid
var parentGrid = button.FindParentOfType<Grid>();
if (parentGrid != null)
{
parentGrid.Background = Brushes.LightBlue;
}
// Find parent UserControl
var parentUserControl = button.FindParentOfType<UserControl>();
if (parentUserControl != null)
{
// Access parent UserControl's properties or methods
((MyUserControl)parentUserControl).DoSomething();
}
}using OliveStudio;
// In a Window or UserControl
private void FindAllTextBoxes()
{
// Find all TextBox controls in the current window
var textBoxes = this.FindVisualChildrenOfType<TextBox>();
foreach (var textBox in textBoxes)
{
textBox.Background = Brushes.Yellow;
Console.WriteLine($"Found TextBox: {textBox.Name}");
}
}
private void ValidateAllInputs()
{
// Find all TextBox controls for validation
var textBoxes = this.FindVisualChildrenOfType<TextBox>();
bool allValid = true;
foreach (var textBox in textBoxes)
{
if (string.IsNullOrWhiteSpace(textBox.Text))
{
textBox.BorderBrush = Brushes.Red;
allValid = false;
}
else
{
textBox.BorderBrush = Brushes.Green;
}
}
if (allValid)
{
MessageBox.Show("All inputs are valid!");
}
}// Custom UserControl
public partial class CustomerEditor : UserControl
{
// Find specific child controls
private void InitializeControls()
{
var nameTextBox = this.FindVisualChildrenOfType<TextBox>()
.FirstOrDefault(tb => tb.Name == "NameTextBox");
var saveButtons = this.FindVisualChildrenOfType<Button>()
.Where(b => b.Content?.ToString()?.Contains("Save") == true);
foreach (var button in saveButtons)
{
button.Click += SaveButton_Click;
}
}
}
// Usage in parent window
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Find all CustomerEditor controls
var customerEditors = this.FindVisualChildrenOfType<CustomerEditor>();
foreach (var editor in customerEditors)
{
// Configure each editor
editor.IsEnabled = CurrentUser.CanEditCustomers;
}
}// In a View's code-behind or attached behavior
public class TextBoxValidationBehavior
{
public static void ValidateAllTextBoxes(DependencyObject parent)
{
var textBoxes = parent.FindVisualChildrenOfType<TextBox>();
foreach (var textBox in textBoxes)
{
// Trigger validation on each TextBox
var bindingExpression = textBox.GetBindingExpression(TextBox.TextProperty);
bindingExpression?.UpdateSource();
}
}
}
// Usage in ViewModel command
public class MainWindowViewModel
{
public ICommand ValidateCommand => new RelayCommand(() =>
{
// Access the view through a service or event
ValidationRequested?.Invoke();
});
public event Action ValidationRequested;
}
// In View code-behind
private void ViewModel_ValidationRequested()
{
TextBoxValidationBehavior.ValidateAllTextBoxes(this);
}public class ControlManager
{
public void DisableAllButtons(Window window)
{
var buttons = window.FindVisualChildrenOfType<Button>();
foreach (var button in buttons)
{
button.IsEnabled = false;
}
}
public void ApplyThemeToControls(DependencyObject root, Brush foreground, Brush background)
{
// Apply to TextBoxes
var textBoxes = root.FindVisualChildrenOfType<TextBox>();
foreach (var textBox in textBoxes)
{
textBox.Foreground = foreground;
textBox.Background = background;
}
// Apply to Labels
var labels = root.FindVisualChildrenOfType<Label>();
foreach (var label in labels)
{
label.Foreground = foreground;
}
}
public List<T> GetControlsWithTag<T>(DependencyObject root, object tag) where T : FrameworkElement
{
var controls = root.FindVisualChildrenOfType<T>();
return controls.Where(c => Equals(c.Tag, tag)).ToList();
}
}public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
SetupEventHandlers();
}
private void SetupEventHandlers()
{
// Find all buttons and attach a common handler
var buttons = this.FindVisualChildrenOfType<Button>();
foreach (var button in buttons)
{
button.MouseEnter += Button_MouseEnter;
button.MouseLeave += Button_MouseLeave;
}
// Find all TextBoxes and attach validation
var textBoxes = this.FindVisualChildrenOfType<TextBox>();
foreach (var textBox in textBoxes)
{
textBox.LostFocus += TextBox_LostFocus;
}
}
private void Button_MouseEnter(object sender, MouseEventArgs e)
{
if (sender is Button button)
{
var parentPanel = button.FindParentOfType<Panel>();
parentPanel?.Children.OfType<TextBlock>()
.FirstOrDefault()?.SetValue(TextBlock.TextProperty, $"Hovering over {button.Content}");
}
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (sender is TextBox textBox)
{
// Find parent form for validation
var parentWindow = textBox.FindParentOfType<Window>();
UpdateValidationStatus(parentWindow);
}
}
}