WPF 绑定模式和绑定源触发器

199 阅读3分钟

绑定模式

绑定模式是用于将控件的属性与数据源连接起来的方式。绑定模式的设定是通过 Mode 属性设置的。

  • OneWay:数据从源到目标单向绑定,目标值会根据源的变化更新,但源的变化不会受到目标的影响。

  • TwoWay:双向绑定,源和目标之间相互更新,任何一方的变化都会同步到另一方。

  • OneWayToSource:数据从目标到源单向绑定,目标的变化会更新源,但源的变化不会影响目标。

  • OneTime:只在绑定初始化时进行一次更新,之后不再响应源的变化。

  • Default:根据控件的默认行为自动选择绑定模式,通常是OneWay

OneWay 单向的

只从源更新目标,这种模式适用于只读数据。

例如:

  • 需要显示当前时间的 TextBlock,只需要从 ViewModel 中绑定时间数据到该控件上即可。
  • 只用来显示滑块组件当前值的 TextBox 。
<Grid>
    <StackPanel>
        <!-- 显示当前时间 -->
        <TextBlock Text="{Binding Time, Mode=OneWay}" >
        <!-- 绑定滑块组件 -->
        <Slider x:Name="sd" Width="200" Height="20" />
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Label Content="滑块当前值" />
            <TextBox Text="{Binding ElementName=sd, Path=Value, Mode=OneWay}" Width="100" />
        </StackPanel>
    </StackPanel>
</Grid>

TwoWay 双向的

源和目标相互更新,这种模式实用于表单数据。

例如:

  • 用户输入表单。

  • 设置界面(如开关、复选框、单选按钮等)。

<TextBox Text="{Binding Name, Mode=TwoWay}" />
<CheckBox IsChecked="{Binding IsFeatureEnabled, Mode=TwoWay}" Content="Enable Feature"/>

过度的使用双向绑定可能会带来一些性能的消耗。

OneWayToSource 仅从目标更新源

仅从目标更新源,这种模式不常见,但也有可能会使用到,例如处理只允许控件更新数据源的场景。

<TextBox Text="{Binding Name, Mode=OneWayToSource}" />

OneTime 一次的

只从源更新一次目标,之后就不再更新。这种模式适用于显示当前版本信息等固定信息后续不会再变更的情况。

<Grid>
    <StackPanel>
        <!-- 显示当前版本 -->
        <TextBlock Text="{Binding Version, Mode=OneTime}" >
    </StackPanel>
</Grid>

这里的版本信息可能是配置文件或者DB读取过来的。所以也需要绑定到目标上。

Default 默认的

如果没有指定绑定模式,WPF会根据控件的默认行为选择绑定模式。对于大部分控件,默认模式是OneWay

默认 Mode 可能为单向,也可能为双向,具体取决于要绑定的依赖属性。 始终可以显式声明绑定模式,以确保绑定具有所需行为。 一般情况下,用户可编辑的控件属性(例如 TextBox.Text 和 RangeBase.Value 默认为双向绑定,但其他大多数属性默认为单向绑定。

默认双向绑定控件:TextBoxComboBoxCheckBoxRadioButtonSlider 等用户输入控件。

默认单向绑定控件:TextBlockImageLabelButtonListBoxDataGrid 等显示数据的控件。

更新源触发器

更新源触发器(UpdateSourceTrigger)用于控制控件(如 TextBox)在双向绑定时何时将控件的值更新回绑定的数据源。默认情况下,WPF 会在控件的值变化时自动更新数据源,但我们可以通过 UpdateSourceTrigger 来更精细地控制数据源的更新时机。

PropertyChanged

每当目标属性更改时立即更新源数据。

<TextBox Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged}" />

LostFocus 失去焦点

当目标控件失去焦点时更新源数据。

<TextBox Text="{Binding UserName, UpdateSourceTrigger=LostFocus}" />

Explicit 明确的

更新源数据必须是在调用了 UpdateSource() 方法时发生。这种的话一般不是在 ViewModel 中调用的。一般是在更XAML文件同名的cs文件中调用,通过某个事件去更新数据源。

<TextBox Text="{Binding UserName, UpdateSourceTrigger=Explicit}" />
var bindingExpression = textBox.GetBindingExpression(TextBox.TextProperty);
bindingExpression.UpdateSource();

Default 默认的

基于目标属性类型的默认行为,大多数控件默认的更新源触发器都是使用的PropertyChanged

立即更新:TextBoxComboBoxSliderProgressBarRadioButtonCheckBox

失去焦点更新:TextBoxPasswordBoxDatePickerComboBox