首页 > 解决方案 > 如何根据 TextBoxes 的内容增加 ProgressBar 的值?

问题描述

所以我有 4 个文本框,并且我已经将 ProgressBar 的最大值设置为4.

ProgressAttr.Maximum = 4;

我想做的是在1每次填写文本框时增加我的 ProgressBar 值。

我的代码现在看起来像这样:

if (!string.IsNullOrEmpty(Name_txtBox.Text))
{
    ProgressAttr.Value += 1;
}

if (!string.IsNullOrEmpty(Serial_TxtBox.Text))
{
    ProgressAttr.Value += 1;
}

if (!string.IsNullOrEmpty(Cap_TxtBox.Text))
{
    ProgressAttr.Value += 1;
}

if (!string.IsNullOrEmpty(IDprk_TxtBox.Text))
{
    ProgressAttr.Value += 1;
}

这不会增加我的 ProgressBar 的值。
我也试过这个:

if (textbox.Text.Length > 0)
{
      ProgressAttr.Value += 1;
}

这些都不适合我,我已经尝试了几个小时寻找解决方案。我非常感谢您的帮助,并期待看到你们提出的解决方案!

标签: c#.netwinformsprogress-bar

解决方案


我建议您使用 DataBindings 将 TextBox 的内容与ValueProgressBar 的属性同步的方法。

类对象可以通知与其实现INotifyPropertyChanged接口的属性值相关的更改。引发其公共PropertyChanged事件以通知绑定控件数据提供者的属性已更改。
然后将所有绑定的属性更新为新值。

这使您可以将所有逻辑放在一个地方,并且对用户界面(此处为您的表单)的更改不会以任何方式影响数据绑定。
您可以在 UI 中添加或删除控件。绑定过程不会更改或需要跟踪 UI 中发生的更改。

例如,将您ProgressBar.Value的属性绑定到该ProgressBarController.Value属性。您使用要包含的 TextBox(或 RichTextBox)控件的实例初始化 ProgressBarController,添加一个 Binding 以链接属性,仅此而已。其余的都是自动发生的。

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);
}

ProgressBar 数据绑定

在这里,两个 TextBox 在加载表单时已经包含一些文本,因此 ProgressBar 显示了一个进度。如果您删除设计器中的所有文本,那么最初显示的进度当然是0


该类ProgressBarController使用其构造函数中传递的控件数组进行初始化。

► 然后它构建一个Dictionary<TextBoxBase, int>来跟踪与控件关联的进度值:0如果其 Text 为空,否则1
TextBoxBase所以你也可以使用 RichTextBox 控件。

TextChanged这些控件的事件是使用单个处理程序订阅的。该sender对象将是引发事件的控件。

► 如果/当关联值已更改(控件文本状态确定更改),PropertyChanged则引发事件并且 DataBinding 通知 ProgressBar 更新其Value属性。

► 当父窗体关闭时,调用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;
        }
    }
}

推荐阅读