Using Silverlight 4 & WPF 4, I\'m trying to create a button style that alters the text color of any contained text when the button is mouseover\'d. Since I\'m trying to make
So after some more thinking, the solution I've ultimately arrived at is to add an attached property to the ContentPresenter element within the button's control template. The attached property accepts a Color and when set examines the visual tree of the content presenter for any TextBlocks, and in turn sets their Foreground properties to the value passed in. This could obviously be expanded/made to handle additional elements but for now it works for what I need.
public static class ButtonAttachedProperties
{
///
/// ButtonTextForegroundProperty is a property used to adjust the color of text contained within the button.
///
public static readonly DependencyProperty ButtonTextForegroundProperty = DependencyProperty.RegisterAttached(
"ButtonTextForeground",
typeof(Color),
typeof(FrameworkElement),
new FrameworkPropertyMetadata(Color.FromArgb(255, 0, 0, 0), FrameworkPropertyMetadataOptions.AffectsRender, OnButtonTextForegroundChanged));
public static void OnButtonTextForegroundChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue is Color)
{
var brush = new SolidColorBrush(((Color) e.NewValue)) as Brush;
if (brush != null)
{
SetTextBlockForegroundColor(o as FrameworkElement, brush);
}
}
}
public static void SetButtonTextForeground(FrameworkElement fe, Color color)
{
var brush = new SolidColorBrush(color);
SetTextBlockForegroundColor(fe, brush);
}
public static void SetTextBlockForegroundColor(FrameworkElement fe, Brush brush)
{
if (fe == null)
{
return;
}
if (fe is TextBlock)
{
((TextBlock)fe).Foreground = brush;
}
var children = VisualTreeHelper.GetChildrenCount(fe);
if (children > 0)
{
for (int i = 0; i < children; i++)
{
var child = VisualTreeHelper.GetChild(fe, i) as FrameworkElement;
if (child != null)
{
SetTextBlockForegroundColor(child, brush);
}
}
}
else if (fe is ContentPresenter)
{
SetTextBlockForegroundColor(((ContentPresenter)fe).Content as FrameworkElement, brush);
}
}
}
and I modified the template like so: