WPF自定义带重置按钮的TextBox控件绑定及交互异常如何解决?
解决方案
所有问题均由控件模板内TextBox与自定义依赖属性的绑定配置缺陷、属性变更逻辑未补全导致,按以下步骤修改即可全部解决:
步骤1:修复模板内TextBox的绑定配置
TemplateBinding为单向轻量绑定,不会传递双向绑定规则与更新源触发配置,直接替换为带RelativeSource的完整绑定即可解决「输入不同步到ViewModel」「重置后文本不更新」两个问题:
修改Generic.xaml中TextBox的Text属性配置:
<TextBox x:Name="PART_InputTextBox" Grid.ZIndex="0" Foreground="{StaticResource RemeberValue_Foreground}" Text="{Binding DisplayText, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch" VerticalAlignment="Center" />
显式指定双向绑定与输入即时更新规则后,用户输入会实时同步到
DisplayText依赖属性,再同步到外层ViewModel;DisplayText后台赋值也会实时刷新到TextBox显示。
步骤2:补全属性变更逻辑,修复重置需点击两次问题
修改RememberValue.cs的后台代码,补全模板控件引用、属性变更回调与重置强制刷新逻辑:
// 注册DefaultValue依赖属性时添加变更回调,同步更新按钮状态 public static readonly DependencyProperty DefaultValueProperty = DependencyProperty.Register(nameof(DefaultValue), typeof(string), typeof(RememberValue), new FrameworkPropertyMetadata(null, OnValueRelatedProperty_Changed)); // DisplayText依赖属性的回调改为共用方法 public static readonly DependencyProperty DisplayTextProperty = DependencyProperty.Register(nameof(DisplayText), typeof(string), typeof(RememberValue), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueRelatedProperty_Changed)); private TextBox _inputTextBox; // 重写模板加载方法,获取内部TextBox实例 public override void OnApplyTemplate() { base.OnApplyTemplate(); _inputTextBox = GetTemplateChild("PART_InputTextBox") as TextBox; } // 共用属性变更回调,更新重置按钮可见性控制属性 private static void OnValueRelatedProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is RememberValue control) { control.IsDifferentValue = !string.Equals(control.DisplayText, control.DefaultValue, StringComparison.Ordinal); } } private void Revert() { // 强制提交文本框未同步的暂存编辑值,解决焦点导致的更新滞后问题 _inputTextBox?.GetBindingExpression(TextBox.TextProperty)?.UpdateSource(); DisplayText = DefaultValue; // 强制刷新文本框显示,消除二次点击问题 _inputTextBox?.GetBindingExpression(TextBox.TextProperty)?.UpdateTarget(); }
可选优化:彻底消除焦点干扰
如果仍偶现点击两次生效的问题,可以在重置方法执行前主动转移焦点,清空文本框的编辑状态滞留:
private void Revert() { // 先将焦点转移到自定义控件本身,清空文本框编辑状态 FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this), this); // 后续逻辑不变 _inputTextBox?.GetBindingExpression(TextBox.TextProperty)?.UpdateSource(); DisplayText = DefaultValue; _inputTextBox?.GetBindingExpression(TextBox.TextProperty)?.UpdateTarget(); }
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

