Charlie Holt

Charlie Holt

  • NA
  • 12
  • 49.7k

Creating a custom solution to link a new instance of a form to a DB?

Dec 3 2010 12:37 AM
I'm using VS2010 with .NET4

Hi all, I'm working on a program that spawns a childform for each row in a database at runtime.  This required some custom solutions and prevented me from using the built-in database interactions.  All of that is working well, but I'm at the point where I'd like to have a button on each childform that will spawn new forms if I need them.

My problem:  I can make the button create a new instance of the form, but I'm unable to link that new form to the database.  I have tried multiple solutions and I've just made a complete mess of it, so I've reverted to the last known 'working' version of my code in the hopes that someone here can help by showing me an easy way to make it happen within the existing framework.

At runtime, Form1 acts as the parent and creates a new instance of DisplayForm for each row in the database.  Each DisplayForm has a button called "buttonNew" that creates a new instance of DisplayForm that needs to be connected to the db.

Db name = MyDatabase.sdf
Table name = MyTable

Form1:
[code]
    public partial class Form1 : Form
    {
        // Adds these private fields, all null by default
        DataSet ds;
        DataTable dt;
        SqlCeConnection cn;
        SqlCeDataAdapter adp;
        SqlCeCommandBuilder cb;

        public Form1()
        {
            InitializeComponent();
        }

        //  This bit helps format the coordinate locations for the childform
        public Point StringToPoint(string str)
        {
            string[] s = str.Split(',');
            int x = Int32.Parse(s[0]);
            int y = Int32.Parse(s[1]);
            return new Point(x, y);
        }

        public void Form1_Load(object sender, EventArgs e)
        {
            //  DB connection
            string fileName = "MyDatabase.sdf";
            string connectionString = string.Format("DataSource=\"{0}\";", fileName);

            //  SQL Command
            string sql = "select * from MyTable";

            try
            {
                cn = new SqlCeConnection(connectionString);

                SqlCeCommand cmd = new SqlCeCommand(sql, cn);

                //  Checking to make sure no concurrent connections exist
                if (cn.State == ConnectionState.Open) cn.Close();

                //  Opening the connection
                cn.Open();

                // create data adapter
                adp = new SqlCeDataAdapter(cmd);

                // create command builder for inserts, updates and deletes
                cb = new SqlCeCommandBuilder();
                cb.DataAdapter = adp;

                // create new dataset and fill it from database
                ds = new DataSet("test");
                adp.Fill(ds);

                // get datatable which is first and only table in dataset
                dt = ds.Tables[0];

                // create MDI child forms and populate their textboxes
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    DataRow row = dt.Rows[i];
                    DisplayForm childForm = new DisplayForm();
                    childForm.Name = "DisplayForm" + i.ToString(); // need a name to distinguish them
                    childForm.MdiParent = this;
                    childForm.Id = (int)row["id"];
                    childForm.Title = (string)row["title"];
                    childForm.Content = (string)row["content"];
                    childForm.Show();
                    childForm.Location = StringToPoint((string)row["location"]);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                // close connection in the event of an exception, otherwise leave it open
                if (cn != null) cn.Close();
            }
        }

        //  The method that updates the DB with the new values
        public void NotifyChanges(DisplayForm childForm)
        {
            int rowIndex = int.Parse(childForm.Name.Substring(11));
            
            // update the appropriate row of the datatable
            dt.Rows[rowIndex]["title"] = childForm.Title;
            dt.Rows[rowIndex]["content"] = childForm.Content;
            
            //  Making sure no NULL location values end up in the database
            if (childForm.DSLocation == null)
            {
                // If NULL, nothing happens...
            }
            else
            {
                dt.Rows[rowIndex]["location"] = childForm.DSLocation;
            }

            // update the datatable
            adp.Update(ds);
        }

        public void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            // close the connection if necessary
            if (cn.State == ConnectionState.Open) cn.Close();
        }
    }
[/code]



DisplayForm:
[code]
    public partial class DisplayForm : Form
    {
        // properties to hold the three fields
        public int Id { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public string DSLocation { get; set; }

        public DisplayForm()
        {
            InitializeComponent();
        }

        public void DisplayForm_Load(object sender, EventArgs e)
        {
            // set initial values
            idTextBox.Text = Id.ToString();
            titleTextBox.Text = Title;
            contentTextBox.Text = Content;
            DSLocation = "1, 1";  //  Needed to set a value for DSLocation - the 1,1 doesn't seem to cause any problems.  Should probably make it a null.

        }

        public void Notebox_LocationChanged(object sender, EventArgs e)
        {
            //  Need to remove LocationChanged - it was a failed attempt that ResizeEnd fixed.
        }

        //  Updates DB when position changes
        public void Notebox_ResizeEnd(object sender, EventArgs e)  //  ResizeEnd fires at the end of a form move, this was the only way I discovered to make this update work properly.
        {
            DSLocation = String.Format("{0},{1}", this.Location.X, this.Location.Y);
            ((Form1)this.MdiParent).NotifyChanges(this);  //  notify parent form that there are changes on this child
        }

        //  Updates DB when title changes
        public void titleTextBox_TextChanged(object sender, EventArgs e)
        {
            // reset properties to new values         
            Title = titleTextBox.Text;
            ((Form1)this.MdiParent).NotifyChanges(this); // notify parent form that there are changes on this child
         }

        //  Updates DB when content changes
        public void contentTextBox_TextChanged(object sender, EventArgs e)
        {
            // reset properties to new values         
            Content = contentTextBox.Text;
            ((Form1)this.MdiParent).NotifyChanges(this); // notify parent form that there are changes on this child
        }
        
        //  THIS IS WHERE THE BUTTON IS
        private void buttonNew_Click(object sender, EventArgs e)
        {
            DisplayForm childForm = new DisplayForm(); // Declare the childform as a new one.
            childForm.MdiParent = this.MdiParent; // Set the mainform as a parent form.
            childForm.Show();// Show the childform.
        }
    }
[/code]

As always, thanks for reading this and lending a hand.  I'm definitely learning, and it's thanks to all of you!
-Charlie


Answers (2)