我建议您使用 DataBindings 将 TextBox 的内容与 ProgressBar 的 Value 属性同步的方法。
类对象可以通知与实现INotifyPropertyChanged 接口的属性值相关的更改。引发其公共PropertyChanged 事件以通知绑定控件数据提供者的属性已更改。
然后将所有绑定的属性更新为新值。
这使您可以将所有逻辑集中在一个位置,并且对用户界面(您的表单,此处为)的更改不会以任何方式影响数据绑定。
您可以在 UI 中添加或删除控件。绑定过程不会更改或需要跟踪 UI 中的更改。
例如,将您的 ProgressBar.Value 属性绑定到 ProgressBarController.Value 属性。您使用要包含的 TextBox(或 RichTextBox)控件的实例初始化 ProgressBarController,将 Binding 添加到 link 属性,仅此而已。其余的都是自动发生的。
ProgressBarController pbarController = null;
// Form Constuctor
public SomeForm()
{
InitializeComponent();
// [...]
// These TextBoxes could be child of a Container (e.g., a Panel), so you could
// also get all the child Controls of this Container to build the array
var textBoxes = new[]{ Name_txtBox, Serial_TxtBox, Cap_TxtBox, IDprk_TxtBox}
ProgressAttr.Maximum = textBoxes.Length;
pbarController = new ProgressBarController(textBoxes);
ProgressAttr.DataBindings.Add("Value", pbarController, "Value", false,
DataSourceUpdateMode.OnPropertyChanged);
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
pbarController.Dispose();
base.OnFormClosed(e);
}
这里,两个 TextBox 在 Form 加载时已经包含了一些文本,所以 ProgressBar 显示了一个进度。如果你删除设计器中的所有文本,当然显示的进度最初是0:
ProgressBarController 类使用其构造函数中传递的控件数组进行初始化。
► 然后它构建一个Dictionary<TextBoxBase, int> 来跟踪与控件关联的进度值:0 如果它的 Text 为空,否则 1。
TextBoxBase 所以你也可以使用 RichTextBox 控件。
► 这些控件的TextChanged 事件使用单个处理程序订阅。 sender 对象将是引发事件的控件。
► 如果/当关联值已更改(控制文本状态确定更改),则引发 PropertyChanged 事件并且 DataBinding 通知 ProgressBar 更新其 Value 属性。
►当Parent Form关闭时,调用该类的Dispose()方法,取消对TextChanged事件的订阅。
using System.Runtime.CompilerServices;
private class ProgressBarController : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
private Dictionary<TextBoxBase, int> states;
private int m_Value = 0;
public ProgressBarController(params TextBoxBase[] tboxes) {
states = new Dictionary<TextBoxBase, int>();
for (int i = 0; i < tboxes.Length; i++) {
states.Add(tboxes[i], tboxes[i].Text.Length > 0 ? 1 : 0);
tboxes[i].TextChanged += TextChanged;
}
m_Value = states.Values.Sum();
}
public int Value {
get => m_Value;
private set {
if (value != m_Value) {
m_Value = value;
OnPropertyChanged();
}
}
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected void TextChanged(object sender, EventArgs e)
{
var tbx = sender as TextBoxBase;
int state = tbx.Text.Length > 0 ? 1 : 0;
if (states[tbx] != state) {
states[tbx] = state;
Value = states.Values.Sum();
}
}
public void Dispose() {
foreach (var tb in states.Keys) {
tb.TextChanged -= this.TextChanged;
}
}
}