There is already an answer showing a guided tool.
Here I expand my comment on debugging InitializeComponent. Suppose basic xaml is a proof of concept.
<Grid> <Grid.Resources> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="Blue" /> </Style> </Grid.Resources> <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="200" Margin="10,25,0,0" VerticalAlignment="Top" Width="199"> <TextBlock Name="analysethis" Text = "why is it blue?" TextWrapping="Wrap" /> </Border> </Grid>
Intercepting the Foreground The TextBlock property is difficult because we cannot subclass TextBlock (otherwise the style will be lost) and we cannot override Freezable . If I have no other solutions, I would set a breakpoint on the next converter
[ValueConversion(typeof(Color), typeof(String))] public class DebugConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (!(value is Color)) return null;
associating it with a TextBlock with a static resource
<TextBlock Name="analysethis" TextWrapping="Wrap" Margin="0,81,0,75" Text="{Binding RelativeSource={RelativeSource Self}, Path=Foreground.Color, Converter={StaticResource ColConv} }" >
After starting Debug, you can see the initial default Foreground assigned to "#FF000000" , and the initial condition is on the stack
System.Xaml.dll!System.Xaml.XamlObjectWriter.Logic_DoAssignmentToParentProperty(MS.Internal.Xaml.Context.ObjectWriterContext ctx) + 0xc6 byte System.Xaml.dll!System.Xaml.XamlObjectWriter.Logic_AssignProvidedValue(MS.Internal.Xaml.Context.ObjectWriterContext ctx) + 0x37 byte
Then there is a second hit at the breakpoint, and the source of the actual foreground color can finally be found on the stack
> PresentationFramework.dll!System.Windows.StyleHelper.DoStyleInvalidations(System.Windows.FrameworkElement fe, System.Windows.FrameworkContentElement fce, System.Windows.Style oldStyle, System.Windows.Style newStyle) + 0xcd byte > WindowsBase.dll!System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex entryIndex, System.Windows.DependencyProperty dp, System.Windows.PropertyMetadata metadata, System.Windows.EffectiveValueEntry oldEntry, ref System.Windows.EffectiveValueEntry newEntry, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType) + 0x757 byte + newEntry {System.Windows.EffectiveValueEntry} System.Windows.EffectiveValueEntry + _value {System.Windows.Style} object {System.Windows.Style} + _value {#FF0000FF} object {System.Windows.Media.SolidColorBrush} + _targetType {System.Windows.Controls.TextBlock} System.Type {System.RuntimeType} > PresentationFramework.dll!System.Windows.FrameworkElement.UpdateStyleProperty() + 0x63 byte
Note that if you are interested, the further PropertyIndex effort shown above (related to Foreground DependencyProperty ) can be traced back to: BamlSchemaContext , the non-public xamlReader member in WpfXamlLoader.LoadBaml , which contains System.Xaml.IXamlLineInfo.LineNumber
Edit
Here's a starter project on how to automate stack trace analysis
[ValueConversion (typeof (Color), typeof (String))] [Serializable] Public class SolidBrushToColorConverter: IValueConverter {
protected MethodInfo EffectiveValueEntryValueGetMethod { get { if (effectiveValueEntryValueGetMethod == null) { var effectiveValueEntryType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(t => t.Name == "EffectiveValueEntry").FirstOrDefault(); if (effectiveValueEntryType == null) throw new InvalidOperationException(); var effectiveValueEntryValuePropertyInfo = effectiveValueEntryType.GetProperty("Value", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.Instance); if (effectiveValueEntryValuePropertyInfo == null) throw new InvalidOperationException(); effectiveValueEntryValueGetMethod = effectiveValueEntryValuePropertyInfo.GetGetMethod(nonPublic: true); if (effectiveValueEntryValueGetMethod == null) throw new InvalidOperationException(); } return effectiveValueEntryValueGetMethod; } } protected MethodInfo EffectiveValuesGetMethod { get { if (effectiveValuesGetMethod == null) { var dependencyObjectType = typeof(DependencyObject); var effectiveValuesPropertyInfo = dependencyObjectType.GetProperty("EffectiveValues", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.Instance); if (effectiveValuesPropertyInfo == null) throw new InvalidOperationException(); effectiveValuesGetMethod = effectiveValuesPropertyInfo.GetGetMethod(nonPublic: true); if (effectiveValuesGetMethod == null) throw new InvalidOperationException(); } return effectiveValuesGetMethod; } } #region Private fields private MethodInfo effectiveValueEntryValueGetMethod; private MethodInfo effectiveValuesGetMethod; #endregion public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (!(value is Color)) return null; var result = value.ToString(); if (result.Equals("#FF0000FF")) { StackTrace st = new StackTrace(); foreach (StackFrame frame in st.GetFrames()) { if (frame.GetMethod().Name.Equals( "UpdateEffectiveValue" )) { foreach (ParameterInfo info in frame.GetMethod().GetParameters()) { Debug.WriteLine ("parameter name " + info.Name + ", type " + info.ParameterType.ToString()); if (info.Name.Equals("newEntry")) { object newEntry = info.GetRealObject(new StreamingContext()); //SET BreakPoint HERE! (to be continued ...) } } } } } return result; }
here is a view of a property found from VS Debugger 