Now Certified in WPF (plus a binding tip)
As the title says, I'm now certified with an MCTS in Windows Presentation Foundation applications, having passed the 70-502 exam. (I've heard it's a tough one.) There were 50 multiple-choice questions to answer in something like 2:30 hours.
As would be expected, the toughest questions were the ones I didn't really have experience in, like aspects of ClickOnce deployment, though these were balanced out by the XAML-related questions.
So anyway, after my moment of euphoria I was working on performing a custom data migration into Dynamics CRM 4, since the Bulk Data Import was inadequate for our mapping needs. I had previously bult a small WPF utility to start a bulk delete of records (for remigrating data), so was in the process of extending it to perform this custom migration.
In this mode, the user selects a CSV file from the file system prior to performing the migration. This is done by clicking a 'browse' button, which displays an OpenFileDialog for the user to select the file. Once the file is 'opened', the adjacent TextBox is updated with the selected path and file name. What makes this interesting is that the application uses the MVVM (Model-View-ViewModel) pattern.
Since it uses the MVVM pattern, the TextBox is bound to the ViewModel in a two-way mode. This means that when the TextBox's Text property is being set programmatically, it uses the code:
csvPath.SetValue(TextBox.TextProperty, selectedFilePath);
rather than:
csvPath.Text = selectedFilePath;
At first, this seemed to work - the TextBox was being updated to show the new value. However when the migration was being performed, stepping through the code revealed that the ViewModel contained the old (default) value.
The solution?
All bindings have an UpdateSourceTrigger property, which determines when the binding source gets updated. Nearly all controls have a default value of PropertyChanged, so that the source is updated as soon as the property value changes. TextBoxes tend to buck the trend and by default, update the source when the TextBox loses focus. Since the property is being set in code, the TextBox never gets focus in order to lose it so that the ViewModel gets updated.
Therefore, the TextBox and its binding should be defined in XAML as follows:
<TextBox x:Name="csvPath" Text="{Binding Path=CsvPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />