Skip to content

数据绑定

使用 Bind 进行双向绑定,使用 OneWayBind 进行单向绑定:

csharp
this.WhenActivated(d =>
{
    // 双向:LineEdit.Text <-> ViewModel.Name
    this.Bind(ViewModel, vm => vm.Name, v => v.NameEdit.Text)
        .DisposeWith(d);

    // 单向 + 转换器
    this.OneWayBind(ViewModel, vm => vm.Score, v => v.ScoreLabel.Text,
            score => $"{score:F1}")
        .DisposeWith(d);

    // 派生值
    this.WhenAnyValue(x => x.ViewModel!.Name, x => x.ViewModel!.Notes)
        .ObserveOn(RxSchedulers.MainThreadScheduler)
        .Subscribe(tuple => { /* 更新 UI */ })
        .DisposeWith(d);
});

属性变更通知的工作原理

两个 binder 协同工作来传递属性变更通知:

GodotPropertyBinder —— 基于信号

订阅 Godot 内置信号,使变更即时到达,没有帧延迟:

控件类型属性Godot 信号
RangeValueValueChanged
LineEditTextTextChanged
TextEditTextTextChanged
BaseButtonButtonPressedToggled
TabContainerCurrentTabTabChanged
TabBarCurrentTabTabChanged
OptionButtonSelectedItemSelected
ColorPickerColorColorChanged
ColorPickerButtonColorColorChanged

GodotPollBasedPropertyBinder —— 逐帧轮询

对于没有专用信号的任意 GodotObject 属性,该 binder 会通过 Observable.PollEveryUpdate 每帧读取值,并在值变化时发出通知。由于依赖轮询,至多存在一帧的延迟。

类型转换器

如果不加上 FloatToDoubleConverter/DoubleToFloatConverter,那么在暴露 double 属性的 Godot 控件(例如 Range.ValueColorPicker.Color)与 ViewModel 的 float 属性之间建立绑定时,会在绑定时抛出 ConverterNotFoundException。本库还附带 EnumToStringConverter<TEnum>StringToEnumConverter<TEnum> 以及 Variant 与基元类型互转的转换器 —— 在 Autoload 引导类中通过 .WithConverter(...) 注册你需要的那部分即可。