WPF UpdateSourceTrigger 是否总是需要通知模型集合中的更改?

Is WPF UpdateSourceTrigger always needed to notify model of changes in collection?

问题:是否总是需要 UpdateSourceTrigger 才能让属性更新源?我似乎记得很久以前 Mode=TwoWay 就足够了。但是现在,我必须 UpdateSourceTrigger=PropertyChanged?也许我正在失去它...

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

当我省略绑定的那一部分时,当 ObservableCollection 中的值发生变化时永远不会调用模型。

绑定的 Mode 和 UpdateSourceTrigger 属性取决于您要绑定的依赖项 属性。根据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.

因此,在您的情况下,您绑定到在 ToogleButton class 中定义的 IsChecked,如下所示:

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)));

所以 BindsTwoWayByDefault 使 Mode=TwoWay 变得多余,而 查询元数据:

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

结果为 PropertyChanged,这使得 UpdateSourceTrigger=PropertyChanged 部分也变得多余。

编辑:关于这部分:

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

真诚地,我无法解释您所注意到的行为(但它很容易重现)。我期待绑定根据依赖项 属性 默认 UpdateSourceTrigger 更新视图模型。但我注意到 ViewModel 甚至不会在焦点丢失时更新,而是在您将焦点移至下一行或按 Enter 键时更新。所以 Colin Eberhardt 在他的 blog 中给出的解释似乎是我能找到的最好的解释。显然,此行为与 DataGrid 密切相关,如果您在网格外有相同的复选框,则 ViewModel 将按预期更新,而无需将 UpdateSourceTrigger 显式设置为 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.

Was UpdateSourceTrigger always necessary to have properties update the source?

没有。绑定的 UpdateSourceTrigger 属性 指定 什么 触发源 属性 的更新,而 Mode 属性 让您控制数据流的方向。这是两个不同的东西。

即使您没有明确设置 UpdateSourceTrigger 属性,您的 Hub 来源 属性 仍然会被设置,但直到您退出DataGrid.

的单元格