Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to display programmatically set Winforms textbox value

Solution

I am now kicking myself over this, but you'll notice in the code below, that I am using a parameterized constructor for Form4. Standard procedure for a parameterized constructor in C# is to use :this() after the declaration (I think, at least for Forms). This calls the unparameterized/default constructor first, which contains InitializeComponent(), which sets up the form and its controls.

InitializeComponent() should most definitely not be in the parameterized constructor if you have used :this(), since it re-initializes your form with 'new' controls. This leads to an ambiguous state for your Form and controls, and the weird behavior I was getting.

Original Question

I have a form in which I would like the controls (including a textbox) to have initial values on first view. The values come from an SQL statement during the Form's construction, so I can't use the Form designer. This form's elements/controls were also copy-pasted from a nearly-identical form since that one is 'Add', and this one is 'Edit'

Problem is this: Using the debugger shows that I successfully get good data from the SQL, and that setting the textbox.Text succeeds, but when the form is displayed, it does not reflect the changes made. The answer here: https://stackoverflow.com/a/7830769/1655707 implies that the value can simply be set (presumably during initialization or load).

I've tried doing it during initialization, in the Load event, and the Shown event, and none of those work. Calling Refresh() and Application.DoEvents() also did nothing. Is there something I am missing? Some event that prevents this textbox from updating/displaying properly? Did copy-pasting the controls have unintended side-effects?

None of the controls I try and set this way display the changed value, but textbox was the simplest since it does not have indices to mess with.

    public Form4(int collIDFromParent, string collNameFromParent): this()
    {
        InitializeComponent();

        retCollID = collIDFromParent;
        retCollName = collNameFromParent;

        //Initialize these here so they activate on first use0
        button1.DialogResult = DialogResult.None;
        button2.DialogResult = DialogResult.Cancel;

        //PopulateEditData goes first for potential SQL failure
        PopulateEditData();

        textBox6.Text = "TEST";
    }

    private void Form4_Load_1(object sender, EventArgs e)
    {
        textBox1.Text = "TEST";
    }

    private void Form4_Shown_1(object sender, EventArgs e)
    {
        textBox2.Text = "TEST";
    }

And yes, they are setting different text boxes, but none of them work, so it makes little difference.

A typical textBox change handler. One might think that the way it's currently written might invoke some sort of resetting, but commenting out that one line does not change the behavior I'm concerned about.

    private void textBox6_TextChanged_2(object sender, EventArgs e)
    {
            retCollName = textBox6.Text;
    }
like image 503
Ruud A. Avatar asked Dec 22 '25 16:12

Ruud A.


1 Answers

With simple changes between functions (such as Add vs Edit), the core functionality of the Form is not going to change. The only core difference between the two functions you are trying to handle is a new object, and an existing object. Because of that, a single Form would be much better instead of two separate forms. It also saves a lot of work, and is one of the cores of OOP.

One other thing I would suggest would be to retrieve the data before you create the form. Create a data object that holds all of your properties you are retrieving from the database. Give that data class a Load method that takes in whatever identifier for which record you are looking for. Now you are set up for an easier time.

I'll make some default buttons here for the sake of examples, your experience may vary. :)

AddButton_Click(//default button click parameters) {
    Widget widget = new Widget();
    OpenWidgetForm(widget);
}

EditButton_Click(//default button click parameters) {
    Widget widget = new Widget();
    // You'll use the way you have now to determine which record to load,
    // and turn it to the id variable
    widget.Load(id);
    OpenWidgetForm(widget);
}

OpenWidgetForm(Widget widget) {
    frmWidget frm = new frmWidget(widget);
    frm.Show();
}

That code will be in whatever form you have that takes you to the Add/Edit forms.

Now in your Add/Edit form, you'll change it around like this:

private Widget _widget;

public frmWidget() {
    Widget widget = new Widget();
    _widget = widget;
    LoadWidget();
}

public frmWidget(Widget widget) {
    _widget = widget;
    LoadWidget();
}

public void LoadWidget() {
    // go through each of the properties of your object
    // and set the values to the Text properties of each Textbox.
    txtName.Text = _widget.Name;
}

With that you should be good to go. Let me know if you have any questions.

like image 176
krillgar Avatar answered Dec 24 '25 05:12

krillgar