Is there a way to attach a handler for the IsVisibleChanged event for a DataGridRow in a DataGridRow style definition? That is, is there a way to do something like the following:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<EventSetter Event="IsVisibleChanged" Handler="OnIsVisibleChanged"/>
</Style>
</DataGrid.RowStyle>
The above won't work because EventSetter can only be applied to RoutedEvents and not regular CLR events, like IsVisibleChanged.
We'll have to make an attached property and an event.
using System;
using System.Windows;
namespace CommonCore.AttachedEvents
{
public static class UIElementHelper
{
public static readonly RoutedEvent IsVisibleChangedEvent = EventManager.RegisterRoutedEvent(
"IsVisibleChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<bool>), typeof(UIElementHelper));
public static void AddIsVisibleChangedHandler(DependencyObject dependencyObject, RoutedPropertyChangedEventHandler<bool> handler)
{
if (dependencyObject is not UIElement uiElement)
return;
uiElement.AddHandler(IsVisibleChangedEvent, handler);
}
private static void RaiseIsVisibleChangedEvent(object sender, DependencyPropertyChangedEventArgs e)
{
((UIElement)sender).RaiseEvent(new RoutedPropertyChangedEventArgs<bool>((bool)e.OldValue, (bool)e.NewValue, IsVisibleChangedEvent));
}
public static void RemoveIsVisibleChangedHandler(DependencyObject dependencyObject, RoutedPropertyChangedEventHandler<bool> handler)
{
if (dependencyObject is not UIElement uiElement)
return;
uiElement.RemoveHandler(IsVisibleChangedEvent, handler);
}
public static bool GetRaiseIsVisibleChanged(UIElement uiElement)
{
return (bool)uiElement.GetValue(RaiseIsVisibleChangedProperty);
}
public static void SetRaiseIsVisibleChanged(UIElement uiElement, bool value)
{
uiElement.SetValue(RaiseIsVisibleChangedProperty, value);
}
// Using a DependencyProperty as the backing store for RaiseIsVisibleChanged. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RaiseIsVisibleChangedProperty =
DependencyProperty.RegisterAttached(
"RaiseIsVisibleChanged",
typeof(bool),
typeof(UIElementHelper),
new PropertyMetadata(false, OnRaiseIsVisibleChanged));
private static void OnRaiseIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not UIElement uiElement)
{
throw new InvalidOperationException("Implemented only for UIElement.");
}
if ((bool)e.NewValue)
{
uiElement.IsVisibleChanged += RaiseIsVisibleChangedEvent;
}
else
{
uiElement.IsVisibleChanged -= RaiseIsVisibleChangedEvent;
}
}
}
}
Their use:
<StackPanel>
<CheckBox x:Name="checkBox"
Content="Visibility"
IsChecked="False"/>
<Border Background="AliceBlue" Padding="10" Margin="10">
<Grid Height="20" Background="Aqua"
Visibility="{Binding IsChecked,
ElementName=checkBox, Converter={commcnvs:BooleanToVisibility}}">
<FrameworkElement.Style>
<Style TargetType="Grid">
<Setter Property="aev:UIElementHelper.RaiseIsVisibleChanged"
Value="True"/>
<EventSetter Event="aev:UIElementHelper.IsVisibleChanged"
Handler="OnIsVisibleChanged"/>
</Style>
</FrameworkElement.Style>
</Grid>
</Border>
</StackPanel>
private void OnIsVisibleChanged(object sender, RoutedPropertyChangedEventArgs<bool> args)
{
MessageBox.Show($"OldValu = {args.OldValue}; NewValue = {args.NewValue};");
}