I recently discovered a nasty little “WPF gotcha.” This issue makes me question whether one should ever hook events of an element in XAML. Basically the problem arises if you hook an element’s event in XAML, set a property of the element which will cause the event to be raised (also in XAML), and in the event handling method reference another element which is declared after that element. You will find that the reference to the other element is null, because the BAML deserialization process hasn’t gotten around to creating that other element yet.
Here’s a stupid example which shows the problem in action. It allows you to pick a word from a ComboBox, and then displays that word in reverse on a TextBlock beneath the ComboBox. The SelectionChanged event of the combo is hooked in XAML so that we can execute the code which reverses the text and display it on the TextBlock (in a real application this type of data manipulation should be done in a value converter). Also note that the ComboBox’s SelectedIndex is set in XAML, which causes the SelectionChanged event to be raised during the BAML deserialization process.
Here’s the OnComboSelectionChanged event handling method, which is referenced in the XAML seen before:
To fix the problem, we can remove the event handler assignment from the XAML and replicate it in code, as seen below:
You would also have to execute the logic which transfers the reversed text to the TextBlock at some point as the Window loads, to handle the initial value of the ComboBox.
Other ways to fix the problem include: set the ComboBox’s SelectedIndex property after the call to InitializeComponent in the constructor, or declare the TextBlock above the ComboBox in XAML, etc.
Download the demo application here: EventHandlersInXAML (demo project) Be sure to change the file extension from .DOC to .ZIP and then decompress it.