-2

Could anyone explain why I get a NullReferenceException, when I create a new Button and try to reference it? Creating the Button and assigning the Name works fine, but referencing it does not.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DragNDrop_1
{
public partial class Form1 : Form
{
    //Variables----------------------------------------------------------------------
    int ButtonID = 100;
    bool isDraggingButton = false;
    public Form1()
    {
        InitializeComponent();
    }
    //----------------------------------------------------------------------Variables
    private void btn_addButton_Click(object sender, EventArgs e)
    {
        AddButton();
    }

    public void AddButton()
    {
        Button b = new Button();
        b.Name = "Button" + ButtonID.ToString();
        b.Text = "Button" + ButtonID.ToString();
        b.Location = new Point(ButtonID, ButtonID);
        ButtonID = ButtonID + 100;
        pnl_DragNDrop.Controls.Add(b);
        isDraggingButton = true;
    }

    private void DragTimer_Tick(object sender, EventArgs e)
    {
        if (isDraggingButton == true)
        {
            Point mouse = PointToClient(MousePosition);
            this.Controls["Button" + ButtonID.ToString()].Location = new Point(mouse.X + 20, mouse.Y + 20);

        }
    }

}
}

The Exception occurs in the timer, where I try to reference the last button created. I read trough some threads regarding this Exception, but I still can't spot the error. Yes, I know that this is very messy and I should propably create a custom Loop or de-/re- activate the timer, but this is just for testing purposes. Note that I'm new to C# and Windows Forms.

EDIT: As explained by Lukasz M, this is a Problem regarding Ownership (maybe the Term is not correct, it's the best german-english Translation I can come up with). This is neither the Focus of the Question from the Thread I "duplicated", nor is it mentioned in the Answer. If it is though, I have to question my English-skills. Anyway, I just wanted to make clear, that I indeed read the Thread, but wasn't able to spot a Solution. Maybe it's just the lack of English- and C#-Skills, but I'm pretty sure that this is not a duplicate.

J.R
  • 11
  • 3
  • 1
    Possible duplicate of [What is a NullReferenceException, and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Matt Rowland Jun 20 '16 at 20:32

1 Answers1

4

It's because in AddButton method You create the button, but do not add it directly to the form's controls, but to the pnl_DragNDrop.Controls collection.

You can try to change this:

this.Controls["Button" + ButtonID.ToString()].Location = new Point(mouse.X + 20, mouse.Y + 20);

to this:

pnl_DragNDrop.Controls["Button" + ButtonID.ToString()].Location = new Point(mouse.X + 20, mouse.Y + 20);

and it should work fine.

Another way to do it would be saving the b button in a class field instead of a variable inside the method. This way, You could refer to the control in a different method without the need to find it by Id in the Controls collection. You may also want to add more than one button with different Id values, so the exact implementation for storing and refering to buttons created then, may depend on actual use case.

Update

To make the code actually work, please also notice that after You create the b control, You modify the variable used to compose its name:

ButtonID = ButtonID + 100;

Then, in DragTimer_Tick method You use the modified value to rebuild the control's name, but it's already different, so the control is not found.

When searching the control by name, You can either save the previous value of ButtonID or save the whole string used as button's name (as mentioned in the comments) to be able to use it to find the control later.

Lukasz M
  • 5,285
  • 2
  • 19
  • 28
  • Unfortunatly (and surprisingly) this didn't work, but I get your Point. However, I was able to understand the Problem and solved it by creating a new Variable(string) and passing it b.Name. – J.R Jun 20 '16 at 21:54
  • It did not work, because after You create the `b` control, You change the `ButtonID` variable (`ButtonID`). After that, when You try to find the control again, You use the modified value. – Lukasz M Jun 20 '16 at 22:18