1
votes

Question: Was UpdateSourceTrigger always necessary to have properties update the source? I seem to recall that Mode=TwoWay was enough a long time ago. But now, I have to UpdateSourceTrigger=PropertyChanged? Maybe I'm losing it...

        <DataGridTemplateColumn  Header="Hub" Width="SizeToHeader">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox x:Name="XHub" IsChecked="{Binding Hub, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

When I omit that part of the binding the model is never called when a value in the ObservableCollection changes.

2
Neither Mode=TwoWay nor UpdateSourceTrigger=PropertyChanged are necessary, because both are the default values.Clemens

2 Answers

1
votes

Both Mode and UpdateSourceTrigger properties of the binding depends on the dependency property you are binding to. According to MSDN:

The default is Default, which returns the default UpdateSourceTrigger value of the target dependency property. However, the default value for most dependency properties is PropertyChanged, while the Text property has a default value of LostFocus.

A programmatic way to determine the default UpdateSourceTrigger value of a dependency property is to get the property metadata of the property using GetMetadata and then check the value of the DefaultUpdateSourceTrigger property.

So in your case you are binding to IsChecked that is defined in ToogleButton class as following:

public static readonly DependencyProperty IsCheckedProperty = 
    DependencyProperty.Register("IsChecked", typeof (bool?), typeof (ToggleButton), 
    (PropertyMetadata) new FrameworkPropertyMetadata(
        BooleanBoxes.FalseBox, 
        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal,
        new PropertyChangedCallback(ToggleButton.OnIsCheckedChanged)));

So BindsTwoWayByDefault makes Mode=TwoWayredundant, while querying metadata:

var def = ((FrameworkPropertyMetadata)CheckBox.IsCheckedProperty.GetMetadata(typeof(CheckBox))).DefaultUpdateSourceTrigger;

results in PropertyChanged, that makes the UpdateSourceTrigger=PropertyChanged part also redundant.

Edit: about this part:

When I omit that part of the binding the model is never called when a value in the ObservableCollection changes.

Sincerely, I cannot explain myself the behavior that you've noticed (but it's quite easy to reproduce). I was expecting the binding to update viewmodel according to dependency property default UpdateSourceTrigger. But I've noticed that the ViewModel is updated not even on focus lost, but when you either move focus to next row or press enter. So the explanation that Colin Eberhardt gives in his blog seems the best I can find. Obviously this behavior is strongly related to DataGrid and if you would have the same checkbox outside of the grid, then the ViewModel would update as expected without explicit UpdateSourceTrigger set to PropertyChanged.

When you bind to a DataTable, you are actually binding to your DataTable's DefaultView, which is of type DataView. As a result, each row of your table will be bound to a DataRowView. If you look at the documentation for DataRowView you will find that it implements the IEditableObject interface which is the significant factor here. This interface allows you to perform transactional changes to your object, i.e. you can change the object's properties within a 'transaction', then commit then all in a single atomic action. By default, when you bind to a DataGrid this occurs when the user finishes editing a row, either by moving focus or hitting Enter.

-1
votes

Was UpdateSourceTrigger always necessary to have properties update the source?

No. The UpdateSourceTrigger property of a binding specifies what triggers the update of a source property whereas the Mode property lets you control the direction of the data flow. These are two different things.

Even if you don't explicitly set the UpdateSourceTrigger property your Hub source property will indeed still be set, but not until the you step out of the cell of the DataGrid.