数据绑定到 TextBox - 在代码中设置 Text 属性不会更新模型



我正在WinForms/C#中处理一些数据收集表单。当表单加载时,我循环通过一个配置,并向每个TextBox控件添加一个新的Binding;将每个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控件中的新值,当用表单重新打开以前输入的记录时,TextBoxes填充了正确的值,并且对以前输入记录的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?当将类似的规则应用于";取消选中";事件处理程序方法中的TextBox以编程方式-CheckBox控件还使用DataBinding对POCO上的布尔属性进行绑定。

当您通过此重载Binding(String, Object, String)设置数据绑定时,DataSourceUpdateMode的值将为OnValidation,这意味着当您使用代码或通过UI修改控件属性的值时,只有在控件发生Validating事件后,绑定才会将新值推送到数据源。

要解决此问题,请使用以下任一选项:

  • 使用另一个过载并将DataSourceUpdateMode设置为OnProperetyChanged
  • OR,在设置了TextBox.Text的值之后,调用表单的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事件为您的布尔属性引发时,您可以检查它是否为false,然后将字符串属性设置为null。

在这种方法中,您不需要处理UI事件。同样,在更新模型属性之后,UI将立即更新;事实上,实现INotifyPropertyChanged可以为您的模型类实现双向数据绑定。

最新更新