Ruud A.
Ruud A.

Reputation: 143

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

Upvotes: 3

Views: 3064

Answers (3)

krillgar
krillgar

Reputation: 12805

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.

Upvotes: 1

Joseph
Joseph

Reputation: 963

This may be a more trivial answer than this problem requires, but make sure you are in fact calling Controls.Add(textBox1). I noticed no one has mentioned this so far. Check in the Designer generated code first.

You will have to call it yourself if you're adding controls dynamically.

Upvotes: 0

Bob
Bob

Reputation: 171

I made a quick project to test this functionality. All three of these choices successfully set the value of the TextBox. You have an issue here that is not shown by the posted code. Either something is changing the TextBox values afterwards, or you're referencing the wrong TextBoxes. I just got done debugging a similar issue with our application. It turned out we somehow had two overlapping sets of TextBoxes (the ones we were actually using were underneath a set of empty TextBoxes).

    public Form1()
    {
        InitializeComponent();

        textBox1.Text = "TEST";
    }

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

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

Upvotes: 0

Related Questions