数据绑定到 TextBox - 在代码中设置 Text 属性不会更新模型
Posted
技术标签:
【中文标题】数据绑定到 TextBox - 在代码中设置 Text 属性不会更新模型【英文标题】:Databinding to TextBox - setting Text property in code doesn't update model 【发布时间】:2021-04-02 04:30:29 【问题描述】:我正在使用 WinForms/C# 处理一些数据收集表单。当表单加载时,我循环配置并为每个 TextBox 控件添加一个新的绑定;将每个 TextBox 控件的 Text 属性映射到我的 POCO 对象上的特定字符串属性。
public void BindTextBoxControls(dynamic entity, List<TextBoxConfig> textBoxConfig)
foreach (var config in textBoxConfig)
config.Control.DataBindings.Add(new Binding("Text", entity, config.PropertyName));
一切都按预期工作,新记录正确保存输入到相应 TextBox 控件中的新值,在重新打开之前使用表单输入的记录时,TextBox 填充了正确的值,并且更新了之前输入记录的 TextBoxes 中的值获取在基础 POCO 上设置的更新值。
但是,我开始在表单上添加一些业务规则,专门根据表单上的其他用户输入/活动来灰显/禁用和清除 TextBox 中先前输入的值 - 事情没有按预期工作。
在一个人为的例子中;一条规则,例如如果选中了 Checkbox_1,则不应评估 TextBox #5(清除任何先前输入的值并将其从输入中禁用)。在 CheckedChanged 的 Checkbox_1 事件处理程序中,我专门检查 Checkbox_1 是否被选中,如果是,则设置 TextBox_1.Text == null 和 TextBox_1.Enabled = false。这按预期工作,在表单上,我看到任何以前输入的值都从 TextBox_1 中清除,并且它已启用。
private void chkCheckBox1_CheckedChanged(object sender, EventArgs e)
if(!chkCheckBox1.Checked)
txtBox5.Text = string.Empty;
但是,当我调试和中断保存并检查调用方法后底层控件绑定到的底层 POCO 属性时;尽管文本框没有值出现在表单上,但旧值仍保留在文本框绑定到的对象属性上。当我重新打开该记录的表单时,旧的清除值会重新填充到禁用的文本框中。但是,手动清除同一 TextBox 中的值或更新值并检查对象会在执行这些操作后显示更新的值。
似乎在代码中更改 TextBox 控件的 Text 值(例如 TextBox 的 Text 属性)可能会以某种方式“绕过”DataBinding?在事件处理程序方法中以编程方式将类似规则应用到“取消选中”文本框时,我实际上看到了相同/相似的行为 - CheckBox 控件也使用 DataBinding 来处理 POCO 上的布尔属性。
【问题讨论】:
【参考方案1】:当你通过这个重载设置数据绑定时:Binding(String, Object, String)
,那么DataSourceUpdateMode
的值将是OnValidation
,这意味着当你使用代码或通过UI修改控件的属性值时,绑定将推送新的仅在控件发生Validating
事件后才向数据源赋值。
要解决此问题,请使用以下任一选项:
使用另一个重载并将DataSourceUpdateMode
设置为OnProperetyChanged
OR,在设置TextBox.Text
的Value 后调用表单的ValidateChildren
方法。
示例 - 将 DataSourceUpdateMode 设置为 OnProperetyChanged
public class Person
public string Name get; set;
public string LegalCode get; set;
public bool IsRealPerson get; set;
Person person;
private void Form1_Load(object sender, EventArgs e)
person = new Person()
Name = "My Company", LegalCode = "1234567890", IsRealPerson = false ;
NameTextBox.DataBindings.Add(nameof(TextBox.Text), person,
nameof(Person.Name), true, DataSourceUpdateMode.OnPropertyChanged);
LegalCodeTextBox.DataBindings.Add(nameof(TextBox.Text), person,
nameof(Person.LegalCode), true, DataSourceUpdateMode.OnPropertyChanged);
IsRealPersonCheckBox.DataBindings.Add(nameof(CheckBox.Checked), person,
nameof(Person.IsRealPerson), true, DataSourceUpdateMode.OnPropertyChanged);
IsRealPersonCheckBox.CheckedChanged += (obj, args) =>
if (IsRealPersonCheckBox.Checked)
LegalCodeTextBox.Text = null;
LegalCodeTextBox.Enabled = false;
;
注意 - 您可以将逻辑放入模型中
另一个解决方案(这需要更多的努力和更多的代码更改)是在你的模型类中实现INotifyPropertyChanged
。然后当 PropertyChanged
为您的布尔属性引发事件时,您可以检查它是否为假,然后您可以将字符串属性设置为 null。
在这种方法中,您不需要处理 UI 事件。同样在更新模型属性后,UI 也会更新;事实上,实现INotifyPropertyChanged
可以为您的模型类启用双向数据绑定。
【讨论】:
以上是关于数据绑定到 TextBox - 在代码中设置 Text 属性不会更新模型的主要内容,如果未能解决你的问题,请参考以下文章
如果 ASP.Net 中的数据库值为空,则在 TextBox 中设置空字符串不起作用
winform中设置dataview.allowedit=false后,怎样使textbox不能修改数据