I am still getting the hang of WPF, so there might be a much better approach, but here is what I thought could work.
Create a ValueTracker
class, this class will provide the following 3 Attached Dependency Properties
TrackProperty - This will be the property of the control that should be tracked
DefaultValue - This is the value that is considered the default, and thing else would trigger the Style trigger.
IsDefaultValue - This will indicate if the current value matches the default, this property will be used in the trigger test.
Here is a quick test, it is not perfect, but I am sure a little tweeking will get things going nicely and of course someone with more WPF experience could improve on this idea.
using System;
using System.Windows;
using System.ComponentModel;
namespace WpfApplication1
{
public static class ValueTracker
{
// Attached dependency property for DefaultValue
public static object GetDefaultValue(DependencyObject obj)
{
return (object)obj.GetValue(DefaultValueProperty);
}
public static void SetDefaultValue(DependencyObject obj, object value)
{
obj.SetValue(DefaultValueProperty, value);
}
public static readonly DependencyProperty DefaultValueProperty =
DependencyProperty.RegisterAttached("DefaultValue",
typeof(object), typeof(ValueTracker), new UIPropertyMetadata(0));
// Attached dependency property for IsDefaultValue
public static bool GetIsDefaultValue(DependencyObject obj)
{
return (bool)obj.GetValue(IsDefaultValueProperty);
}
private static void SetIsDefaultValue(DependencyObject obj, bool value)
{
obj.SetValue(IsDefaultValueProperty, value);
}
public static readonly DependencyProperty IsDefaultValueProperty =
DependencyProperty.RegisterAttached("IsDefaultValue",
typeof(bool), typeof(ValueTracker), new UIPropertyMetadata(false));
// Attached dependency property for TrackedProperty
public static DependencyProperty GetTrackProperty(DependencyObject obj)
{
return (DependencyProperty)obj.GetValue(TrackPropertyProperty);
}
public static void SetTrackProperty(DependencyObject obj, DependencyProperty value)
{
obj.SetValue(TrackPropertyProperty, value);
}
public static readonly DependencyProperty TrackPropertyProperty =
DependencyProperty.RegisterAttached("TrackProperty",
typeof(DependencyProperty), typeof(ValueTracker),
new UIPropertyMetadata(TrackPropertyChanged));
public static void TrackPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DependencyProperty oldProperty = e.OldValue as DependencyProperty;
if (oldProperty != null)
{
DependencyPropertyDescriptor dpd =
DependencyPropertyDescriptor.FromProperty(oldProperty, typeof(UIElement));
if (dpd != null)
{
dpd.RemoveValueChanged(d, TrackedPropertyValueChanged);
}
}
DependencyProperty newProperty = e.NewValue as DependencyProperty;
if (newProperty != null)
{
DependencyPropertyDescriptor dpd =
DependencyPropertyDescriptor.FromProperty(newProperty, typeof(UIElement));
if (dpd != null)
{
dpd.AddValueChanged(d, TrackedPropertyValueChanged);
}
}
}
private static void TrackedPropertyValueChanged(object sender, EventArgs e)
{
DependencyObject o = sender as DependencyObject;
if (o != null)
{
object defaultValue = Convert.ChangeType(GetDefaultValue(o), GetTrackProperty(o).PropertyType);
SetIsDefaultValue(o, Object.Equals(o.GetValue(GetTrackProperty(o)), defaultValue));
}
}
}
}
The above can be used as follows.
1- Create a style which triggers on the ValueTracker.IsDefaultValue
2- For each control that you want to track, you attach the style and set the ValueTracker.DefaultValue and set the property that should be tracked using the ValueTracker.TrackProperty.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:r="clr-namespace:WpfApplication1"
mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow"
d:DesignHeight="221" d:DesignWidth="287"
Width="250" Height="250">
<StackPanel Loaded="StackPanel_Loaded" >
<StackPanel.Resources>
<Style TargetType="{x:Type Control}" x:Key="trackChanges">
<Style.Triggers>
<Trigger Property="local:ValueTracker.IsDefaultValue" Value="false">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<TextBox Name="textbox1" Width="100" Height="23"
local:ValueTracker.DefaultValue="Help"
local:ValueTracker.TrackProperty="TextBox.Text"
Style="{StaticResource ResourceKey=trackChanges}" />
<ComboBox Name="combobox1"
SelectedIndex="2"
local:ValueTracker.DefaultValue="2"
local:ValueTracker.TrackProperty="ComboBox.SelectedIndex"
Style="{StaticResource ResourceKey=trackChanges}">
<ComboBox.Items>
<ComboBoxItem>Item 1</ComboBoxItem>
<ComboBoxItem>Item 2</ComboBoxItem>
<ComboBoxItem>Item 3</ComboBoxItem>
<ComboBoxItem>Item 4</ComboBoxItem>
</ComboBox.Items>
</ComboBox>
</StackPanel>
</Window>