I have a small 'rolodex' program that opens a form for each person in my
database at runtime (each person is a row in the db). I have that part
working (thanks to some help from the lovely people here!), but I have a
new problem. I am no longer able to edit the information in the
textboxes on the forms that have been populated by the database...
After doing some research, I realize that I'm failing to bind the data
in the instanced forms to its row in the database. After a week of
reading and trying different examples all over the net, I'm still stuck.
My question is: How do I instance new forms (childforms) and bind each
form to its proper row in the database so that I can edit the contents
of the textboxes and have those changes saved in the database?
I'm using VisualStudio 2010 and .Net 4 on a Win7 64 machine.
My database is called PeopleDatabase.sdf
The table is called PeopleTable
Form1 is the 'environment' for the program - all Peoplebox appear inside of it at runtime.
Peoplebox is the form that shows the data queried from the database. It
has 3 textboxes on it that need to be bound to the same row in the
database. A different Peoplebox appears for each row in the database.
Form1:
[code]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlServerCe;
namespace MaryAnne
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void Form1_Load(object sender, EventArgs e)
{
// DB connection
string fileName = "PeopleDatabase.sdf";
string connectionString = string.Format("DataSource=\"{0}\";", fileName);
// SQL Command
string sql = "select * from PeopleTable";
SqlCeConnection cn = null;
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();
SqlCeDataReader scdr = cmd.ExecuteReader();
while (scdr.Read())
{
// Opening a Peoplebox for each row in the DB
Peoplebox childForm = new Peoplebox();
childForm.MdiParent = this;
childForm.IdMessage = (int)scdr["id"];
int newIdMessage = childForm.IdMessage;
childForm.TitleMessage = (string)scdr["title"];
string newTitleMessage = childForm.TitleMessage;
childForm.ContentMessage = (string)scdr["content"];
string newContentMessage = childForm.ContentMessage;
childForm.Show();
}
scdr.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (cn != null)
cn.Close();
}
}
}
}
[/code]
Peoplebox:
[code]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MaryAnne
{
public partial class Peoplebox : Form
{
public Peoplebox()
{
InitializeComponent();
}
// Defining all the variables coming from the DB
// ID
private int _IdMessage;
public int IdMessage
{
get { return _IdMessage; }
set { _IdMessage = value; }
}
// TITLE
private string _TitleMessage;
public string TitleMessage
{
get { return _TitleMessage; }
set { _TitleMessage = value; }
}
// CONTENT
private string _ContentMessage;
public string ContentMessage
{
get { return _ContentMessage; }
set { _ContentMessage = value; }
}
// DB connection
public void PeopleTableBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.Validate();
this.PeopleTableBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.PeopleDatabaseDataSet);
}
public void Peoplebox_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'PeopleDatabaseDataSet.PeopleTable' table. You can move, or remove it, as needed.
this.PeopleTableTableAdapter.Fill(this.PeopleDatabaseDataSet.PeopleTable);
}
public void PeopleboxSibling_Click(object sender, EventArgs e)
{
Peoplebox childForm = new Peoplebox(); // Declare the child form as a new one.
childForm.MdiParent = this.MdiParent; // Set the main form as a parent form.
childForm.Show();// Show the child form.
}
public void idTextBox_TextChanged(object sender, EventArgs e)
{
idTextBox.Text = IdMessage.ToString();
}
public void titleTextBox_TextChanged(object sender, EventArgs e)
{
titleTextBox.Text = TitleMessage;
}
public void contentTextBox_TextChanged(object sender, EventArgs e)
{
contentTextBox.Text = ContentMessage;
}
}
}
[/code]
Thank you so much for reading this far! I'm looking forward to the day when I'll know enough to help others out...
-MaryAnne
Loading
Sam HobbsPosted Nov 20, 2010, 2:48 AM
Mary AnnePosted Nov 20, 2010, 2:21 AM
-MaryAnne
Sam HobbsPosted Nov 20, 2010, 1:57 AM
I am not aware of any articles or tutorials but this web site has many articles and there are probably some that will help. I will make a step-by-step list of what I said. Note that when I say parameter, I mean something that provides the data that uniquely identifies what record that the form is to show, such as the person's id number or their name.
Mary AnnePosted Nov 20, 2010, 1:18 AM
-MaryAnne
Sam HobbsPosted Nov 20, 2010, 1:04 AM
Mary AnnePosted Nov 20, 2010, 12:58 AM
But I think we're getting sidetracked... My question is still 'how do I create a Peoplebox for each row in the db at runtime AND have the textboxes in each Peoplebox be bound to the correct row/column in the db'?
Thanks for hashing this out with me, Sam.
Edit: I don't know if you edited your last response or if I just completely missed the second half of it... My apologies either way. Are you aware of a tutorial or lengthy explanation someone's already typed up of the method you described? Reading it melted my brain and I fear I'll need more information.
-MaryAnne
Sam HobbsPosted Nov 20, 2010, 12:40 AM
I will jump ahead and try to guess at a solution.
I think you need to modify the PeopleTableTableAdapter to add a parameter. Use the database designer to do that. The Fill method will then have a parameter that must be provided. You will need a member variable and/or property in the child form for the parameter and a way to set it from the main form and then use the parameter in the Fill in the form load.
Mary AnnePosted Nov 20, 2010, 12:29 AM
You fully understand what I am trying to do, but you are incorrect about my intention. Using one childform to cycle through the multiple db rows would be easy (so easy that the IDE handles everything automatically). That is not my intention. I would like a separate childform for each row in the db to allow the user to position each person anywhere on the screen. It's a proof-of-concept project to help me learn the intricacies of C# and VisualStudio (I come from a php/python background).
No one seems to understand (or be able to easily explain) data bindings - especially for assigning bound values to instanced forms. I've done my homework and I cannot find a solution. I'm hoping someone here will be able to lend a hand. And I hope I've clarified what I'm trying to accomplish.
-MaryAnne
Sam HobbsPosted Nov 20, 2010, 12:12 AM
Let's start by clarifying what you are doing. You have a main form that is the MDI parent that is for contaiing the MDI chiild forms. When the form loads, it creates childs forms; one instance per person record. Am I correct so far?
Am I correct that you intend to show the details of one person at a time; only one at a time? If so then will you consider an alternative design?