C# getting information in the behind form - c#

I have two forms
the first one is FrmReceiveItems from which I can display the second one
FrmItemSearch. In the second one I can choose a certain item to add to a DataGridView in the first form. The problem is that whenever I add an item I will have a new object from the first form. I want all chosen items to be added to the first opened form. I try to test if any object of the first form is opened .. as following:
private void dgv_ItemsSearch_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
try
{
//Connection obj = new Connection();
//Connection.FrmChose = 10;
FrmRecieveItemsVoucher FRI = new FrmRecieveItemsVoucher();
Form frmT = Application.OpenForms["FRI"];
int value = Connection.FrmChose;
if (value == 10)
{
FRI.dataGridView_ItemsVoucher.Rows.Add();
int CurrentRowIndex = FRI.dataGridView_ItemsVoucher.Rows.Count;
FRI.dataGridView_ItemsVoucher.Rows[CurrentRowIndex - 1].Cells[0].Value = dgv_ItemsSearch.CurrentRow.Cells[2].Value;
FRI.dataGridView_ItemsVoucher.Rows[CurrentRowIndex - 1].Cells[1].Value = dgv_ItemsSearch.CurrentRow.Cells[1].Value;
// here I try to test
if (frmT != null)
{
this.Dispose();
}
else
{
FRI.Show();
}
}
else
{
FrmItems frmItems = new FrmItems();
//frmCust.btn_new(sender,e);
string Code = Convert.ToString(dgv_ItemsSearch.CurrentRow.Cells[2].Value);
this.Dispose();
frmItems.Show();
frmItems.Show_Record_data(Code);
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}

well there are a lot of ways to achieve this. What I would personally go for is creating a BindingList and setting a ListChanged event on that list that would then trigger a reload in the second form.

Related

The FormClosing event seems to run after a different Form is started

I did a lot of research about this problem and tried methods but none of them worked. First I will show you what is in my application and what I want it to be with some pictures.
Picture 1
As you can see in the first picture, I open new childForms using the buttons on the main form. One of them is the form named "Price". This form saves the prices entered by the user to the json file. I do the saving process in the FormClosing event. (Yes i know but I don't want to use the "Save" button.)
Picture 2
As you can see in the second picture, the "Result" form did some mathematical operations by reading the values entered by the user in the "Price" form over json.
Now let's come to the problem, I open the "Price" form, change the values and press the result button. Results are coming, everything is great! But the results are not correct because when the "Result" Form was run it didn't wait for the current values to be saved in json. So it didn't wait for the "Price" form to close (i.e. it didn't wait for the Price.FormClosing event to complete).
To avoid this error, I open the results form after opening a different form, but this is amateurish.
I hope I was able to explain my problem clearly.
Thanks in advance for your answers and thoughts.
Code to Write Current Values to JSON File:
private void ProductPricesForm_FormClosing(object sender, FormClosingEventArgs e)
{
string jsonString = JSONOperations.getItemsAsString(products);
File.WriteAllText(JSONOperations.productsJSONPath, jsonString);
}
Code to Read JSON File:
private static void getItems()
{
using (StreamReader r = new StreamReader(JSONOperations.productsJSONPath))
{
string json = r.ReadToEnd();
products = JSONOperations.getItemsAsClass<Product>(json);
}
}
Form Opening Code:
private void buttonResult_Click(object sender, EventArgs e)
{
openChildForm(new ResultForm());
}
private void buttonProductPrices_Click(object sender, EventArgs e)
{
openChildForm(new ProductPricesForm());
}
private Form activeForm;
private void openChildForm(Form childForm)
{
if (activeForm == null)
{
startChildForm(childForm);
}
else
{
if (String.Equals(activeForm.Name, childForm.Name))
{
return;
}
else if (!String.Equals(activeForm.Name, childForm.Name))
{
activeForm.Close();
startChildForm(childForm);
}
}
}
private void startChildForm(Form childForm)
{
childForm.TopLevel = false;
childForm.FormBorderStyle = FormBorderStyle.None;
childForm.Dock = DockStyle.Fill;
panelChildForm.Controls.Add(childForm);
panelChildForm.Tag = childForm;
childForm.BringToFront();
childForm.Show();
activeForm = childForm;
}
You can simply Hide the dialog instead of close.
First, create your childs types:
private enum FormType
{
Result = 0,
Products = 1,
//...
}
An a method to create each form:
private Form CreateChildForm(FormType formType)
{
switch (formType)
{
case FormType.Result:
return new ResultForm();
case FormType.Products:
return new ProductPricesForm();
default:
return null;
}
}
Now, in your form, add this fields:
private int _activeChildIndex = -1;
private readonly Form[] _childsForms = new Form[Enum.GetNames(typeof(FormType)).Length];
_childsForms will store each type of ChildWindow that you create. _activeChildIndex indicates the _childsForms which is active now.
private void ShowChildWindow(FormType formType)
{
var index = (int)formType;
if (this._activeChildIndex == index)
{
return;
}
if (this._activeChildIndex >= 0)
{
var activeChild = this._childsForms[this._activeChildIndex];
// TODO: Hide form
this.OnHideForm(this._activeChildIndex);
}
this._activeChildIndex = index;
if (this._childsForms[index] != null)
{
// TODO: Reset to default (or leave with last state, as you prefer)
// TODO: And show
}
else
{
// TODO: Create child form
var childForm = this.CreateChildForm(formType);
if (childForm != null)
{
this._childsForms[index] = childForm;
}
}
this.OnShowForm(this._activeChildIndex);
}
This method create a child form if not exists and show when was previously created.
In your ProductsForm, add a method to get the JSON:
public string GetProductsJson()
{
return JSONOperations.getItemsAsString(products);
}
Now, you can use OnShowForm in this way:
private void OnShowForm(int index)
{
var formType = (FormType)index;
if (formType == FormType.Result)
{
var productsForm = this._childsForms[(int)FormType.Products];
if (productsForm != null)
{
var json = productsForm.GetProductsJson();
}
}
}
When you activate your result form, search your products form. If was previously created, get the Json. You don't need save to file the json to use here. Save it if you need for other reason.
Do some changes in FormClosing:
private void ProductPricesForm_FormClosing(object sender, FormClosingEventArgs e)
{
// Do this if you need
string jsonString = GetProductsJson();
File.WriteAllText(JSONOperations.productsJSONPath, jsonString);
// TODO: You need a flag to know when are you closing the app.
// In that case, don't cancel
e.Cancel = true;
}
UPDATE
I don't like this solution but may be that you are waiting for:
First, add a method to get the Json in your Product form:
public string GetJson()
{
return JSONOperations.getItemsAsString(products);
}
And a field in your main form:
private string _productsJson;
Instead of a file, use this string. You also can save to file if you need for other purposes.
Change this other method:
private void buttonProductPrices_Click(object sender, EventArgs e)
{
var form = new ProductPricesForm();
form.FormClosing += (sender2, e2) => this.OnProductsPrices(form.GetJson());
openChildForm(form);
}
It do the same as you was doing and also get the closing event to get the Json and invoke to OnProductsPrices with that string.
private void OnProductsPrices(string json)
{
if (_productsJson != json)
{
_productsJson = json;
var form = activeForm as ResultForm;
if (form != null)
{
form.DoSomethingWithTheJson(json);
}
}
}
If the Json doesn't change, you don't need to do anything. When it's changed, you update your _productsJson and check if current form is ResultForm. In this case, you load the Json or do whatever you do with the Json in that Form.
Also, you must use _productsJson when you create the ResultForm, like know, that I suppose you get from file. In this way, you use the json always when you create ResultForm or later, when the ProductsForm is closed.
private void buttonResult_Click(object sender, EventArgs e)
{
var form = new ResultForm();
openChildForm(form);
if (!string.IsNullOrEmpty(_productsJson))
form.DoSomethingWithTheJson(_productsJson);
// Or do the same in the constructor and manage inside the form, calling to DoSomethingWithTheJson
//var form = new ResultForm(_productsJson);
}

How do i add a previous and next button to datagridview

I am using Visual studio 2012 and have made a windows form application, for one of the forms I am using a datagridview which shows the information of a table from the SQL database.
I have made the form load information from the datagridview rows directly into a textbox automatically.
SqlDataAdapter SDA = new SqlDataAdapter("SELECT * FROM Stock", con);
DataTable DATA = new DataTable();
SDA.Fill(DATA);
dataGridView1.DataSource = DATA
txtStock3.Text = dataGridView1.SelectedRows[0].Cells[0].Value.ToString();
Descriptioncombo2.Text = dataGridView1.SelectedRows[0].Cells[1].Value.ToString();
txtprice2.Text = dataGridView1.SelectedRows[0].Cells[2].Value.ToString();
The problem is that I need to add a previous button and a next button so that users can navigate through the datagridview rows and see the information in a textbox from each column of a datagridview row. I have looked at similar questions and have browsed through the internet to look for a solution to my problem but i can't seem to find a way which works with my code. Also could you tell me how to add a line of code which tells the user that there is no more rows to select if they click next through all rows of the database.
One way to provide navigation is by using a BindingNavigator where you can remove unnecessary buttons and for TextBox you can data binding.
Code responsible for loading data. Replace the console.writeline in the catch as you see fit e.g. write to a log file etc.
public class DataOperations
{
public DataTable LoadCustomers()
{
DataTable dtCustomers = new DataTable();
using (SqlConnection cn = new SqlConnection(Properties.Settings.Default.ConnectionString))
{
string commandText = #"SELECT [Identfier], [CompanyName],[ContactName],[ContactTitle] FROM [NORTHWND1.MDF].[dbo].[Customers]";
using (SqlCommand cmd = new SqlCommand(commandText, cn))
{
try
{
cn.Open();
dtCustomers.Load(cmd.ExecuteReader());
dtCustomers.Columns["Identfier"].ColumnMapping = MappingType.Hidden;
dtCustomers.Columns["ContactTitle"].ColumnMapping = MappingType.Hidden;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
return dtCustomers;
}
}
On a form, one BindingNavigator, one dataGridView, one TextBox
DataOperations dataOps = new DataOperations();
BindingSource bsCustomers = new BindingSource();
bsCustomers.DataSource = dataOps.LoadCustomers();
dataGridView1.DataSource = bsCustomers;
bindingNavigator1.BindingSource = bsCustomers;
txtContactTitle.DataBindings.Add("Text", bsCustomers, "ContactTitle");
An alternate to the BindingNavigator is to make the BindingSource form level, private variable. Then in buttons call BindingSource.Move method e.g. bsCustomers.MoveFirst(). Of course there is MoveNext, MoveLast and MovePrevious too.
//first
int i = 0;
this.dataGridView1.CurrentCell = dataGridView1.Rows[0].Cells[dataGridView1.CurrentCell.ColumnIndex];
//prev
int prev = dataGridView1.CurrentRow.Index - 1;
if (prev >= 0)
{
this.dataGridView1.CurrentCell = dataGridView1.Rows[prev].Cells[dataGridView1.CurrentCell.ColumnIndex];
//MessageBox.Show(dataGridView1[0, dataGridView1.CurrentRow.Index].Value.ToString());
}
//next
int next = dataGridView1.CurrentRow.Index + 1;
if (next < dataGridView1.Rows.Count)
{
this.dataGridView1.CurrentCell = dataGridView1.Rows[next].Cells[dataGridView1.CurrentCell.ColumnIndex];
//MessageBox.Show(dataGridView1[0, dataGridView1.CurrentRow.Index].Value.ToString());
}
//last
int i = dataGridView1.Rows.Count - 1;
if (i < dataGridView1.Rows.Count)
{
this.dataGridView1.CurrentCell = dataGridView1.Rows[i].Cells[dataGridView1.CurrentCell.ColumnIndex];
//MessageBox.Show(dataGridView1[0, dataGridView1.CurrentRow.Index].Value.ToString());
}
As an alternate to Karen's solution, if you prefer/must go with buttons to navigate then you'll want to handle the CurrentCellChanged event as well as the following button Click events:
private void DataGridView1_CurrentCellChanged(object sender, EventArgs e)
{
if (this.dataGridView1.CurrentRow != null)
{
txtStock3.Text = dataGridView1.CurrentRow.Cells[0].Value.ToString();
Descriptioncombo2.Text = dataGridView1.CurrentRow.Cells[1].Value.ToString();
txtprice2.Text = dataGridView1.CurrentRow.Cells[2].Value.ToString();
this.prevButton.Enabled = this.dataGridView1.CurrentRow.Index > 0;
this.nextButton.Enabled = this.dataGridView1.CurrentRow.Index < this.dataGridView1.Rows.Count - 1;
}
}
private void PrevButton_Click(object sender, EventArgs e)
{
int prev = this.dataGridView1.CurrentRow.Index - 1;
this.dataGridView1.CurrentCell = this.dataGridView1.Rows[prev].Cells[this.dataGridView1.CurrentCell.ColumnIndex];
}
private void NextButton_Click(object sender, EventArgs e)
{
int next = this.dataGridView1.CurrentRow.Index + 1;
this.dataGridView1.CurrentCell = this.dataGridView1.Rows[next].Cells[this.dataGridView1.CurrentCell.ColumnIndex];
}
The CurrentCellChanged event will handle logic for if you can click Previous or Next. Their respective click events simply move the current cell backwards or forwards one row.
You configure the comulmns in the grid to be your matching types. Then after the query you bind the data to this gridView. You add two buttons where the "next" button will fetch the currentselectedrow of the grid, and set it's follower to be the selected one. previous will do the opposite. This is a small pain in the ass. I hate grids in WinForms. The last 4 years, since I did not see them, have been the happiest years of my lif

Must I remove a form assigned to a TabPage and then add a new one, or can I access the existing one to change values it contains dynamically?

I am dynamically assigning forms to tab pages. It works fine, except when I try to assign
an updated version of the form (with different text values assigned to the controls) to the tab page. I am actually a little surprised that it doesn't crash when I create multiple instances of the form and assign them to the tab page (if the new ones are just stacking on top of the older ones, you would think the new one would be on top and the new values are visible).
So...what do I need to do to remove the previous form I added to the tab page before adding the new version? Or can I access the existing form and change its values.
I guess it would be clearer if I just showed the code:
Main form:
private enum TabControls {
BasicInfo,
ConfidentialInfo,
RolesAndSecurity,
InactiveInfo
}
string currentNode = string.Empty;
public Form1() {
InitializeComponent();
CenterToScreen();
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) {
currentNode = e.Node.Name;
UpdateActiveTabForNode();
}
// This is called both by treeView1_AfterSelect (sic, I changed the name to
// treeViewSearchWorker) and by tabControlWorker_SelectedIndexChanged().
// currentNode is set/overwritten on clicking a node and saved in a form var.
// The active tab page is always known via the TabControl's SelectedIndex
// property, so there is no need to pass in either value.
private void UpdateActiveTabForNode() {
int ActiveTabPage = tabControlWorker.SelectedIndex;
switch (ActiveTabPage) {
case (int)TabControls.BasicInfo:
if (tabPageBasicInfo.Controls.Count > 0) {
;// tabPageBasicInfo.Controls.Remove(0);<-- What to pass in here?
}
BasicInfoPseudoTab bipt = new BasicInfoPseudoTab(currentNode);
tabPageBasicInfo.Controls.Add(bipt);
tabPageBasicInfo.BringToFront();
bipt.Show();
break;
case (int)TabControls.ConfidentialInfo:
ConfidentialInfoPseudoTab cipt = new ConfidentialInfoPseudoTab(currentNode);
tabPageConfidentialInfo.Controls.Add(cipt);
cipt.Show();
break;
case (int)TabControls.RolesAndSecurity:
RolesAndSecurityPseudotab raspt = new RolesAndSecurityPseudotab(currentNode);
tabPageRolesAndSecurity.Controls.Add(raspt);
raspt.Show();
break;
case (int)TabControls.InactiveInfo:
InactiveInformationPseudoTab iipt = new InactiveInformationPseudoTab(currentNode);
tabPageInactiveInfo.Controls.Add(iipt);
iipt.Show();
break;
default: {
break;
// TODO: Do something?
}
}
}
private void tabControlWorker_SelectedIndexChanged(object sender, System.EventArgs e) {
UpdateActiveTabForNode();
}
}
====
Form that serves as one of the pseudo tabPages:
public partial class BasicInfoPseudoTab : Form {
String _aNodeName = String.Empty;
public BasicInfoPseudoTab(String ANodeName) {
InitializeComponent();
// Without this, you get "TopLevel control cannot be added to a control"
this.TopLevel = false;
this.FormBorderStyle = FormBorderStyle.None;
this.Visible = true;
this.Dock = DockStyle.Fill;
_aNodeName = ANodeName;
SetDisplayVals();
}
private void SetDisplayVals() {
if (_aNodeName == "NodeBuckingham") {
textBoxFirstName.Text = "Buckingham";
textBoxLastName.Text = "Piranha";
textBoxNickname.Text = "B.P.";
}
else if (_aNodeName == "NodeVolcano") {
textBoxFirstName.Text = "Volcano";
textBoxLastName.Text = "Jerry";
textBoxNickname.Text = "V.J.";
} else if (_aNodeName == "NodeParsons") {
textBoxFirstName.Text = "Parsons";
textBoxLastName.Text = "Spalding";
textBoxNickname.Text = "P.S.";
} else {
textBoxFirstName.Text = String.Empty;
textBoxLastName.Text = String.Empty;
textBoxNickname.Text = String.Empty;
}
}
Updated:
I got it working by declaring the form variables outside the event handler and disposing them if they were not null before proceeding.
string currentNode = string.Empty;
BasicInfoPseudoTab bipt;
ConfidentialInfoPseudoTab cipt;
RolesAndSecurityPseudotab raspt;
InactiveInformationPseudoTab iipt;
. . .
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) {
currentNode = e.Node.Name;
UpdateActiveTabForNode();
}
private void UpdateActiveTabForNode() {
int ActiveTabPage = tabControlWorker.SelectedIndex;
switch (ActiveTabPage) {
case (int)TabControls.BasicInfo:
if (null != bipt) {
bipt.Dispose();
}
bipt = new BasicInfoPseudoTab(currentNode);
tabPageBasicInfo.Controls.Add(bipt);
bipt.Show();
break;
. . .
As you wish, use module level variables, one for each form, if null, new it, else as above. If you are creating forms constantly on top of each other how are you ever going to clean up? Check the size of your working set as you keep creating forms.

Skip to a database record in c#

Here is some background on what I have been following.
http://www.homeandlearn.co.uk/csharp/csharp_s12p9.html
That will go to the last or first record of the database. I want to skip to a record in the access database that the user wants by inputting the ID number in a textbox and then the correct row will get put in the textboxes.
I think I can use this code from the above website. I have implemented everything else from the website above.
Global variable
int inc = 0;
The navigate records that I will call in my Skip button later
private void NavigateRecords()
{
DataRow dRow = ds1.Tables["Laptops"].Rows[inc];
txtMaker.Text = ds1.Tables["Laptops"].Rows[inc].ItemArray.GetValue(1).ToString();
txtModel.Text = ds1.Tables["Laptops"].Rows[inc].ItemArray.GetValue(2).ToString();
txtPrice.Text = ds1.Tables["Laptops"].Rows[inc].ItemArray.GetValue(3).ToString();
txtBids.Text = ds1.Tables["Laptops"].Rows[inc].ItemArray.GetValue(4).ToString();
txtScreen.Text = ds1.Tables["Laptops"].Rows[inc].ItemArray.GetValue(5).ToString();
txtCPU.Text = ds1.Tables["Laptops"].Rows[inc].ItemArray.GetValue(6).ToString();
txtMemory.Text = ds1.Tables["Laptops"].Rows[inc].ItemArray.GetValue(7).ToString();
txtHD.Text = ds1.Tables["Laptops"].Rows[inc].ItemArray.GetValue(8).ToString();
picLaptops.Image = Image.FromFile(ds1.Tables["Laptops"].Rows[inc].ItemArray.GetValue(9).ToString());
}
My skip button so far...
private void btnSkip_Click(object sender, EventArgs e)
{
NavigateRecords();
}
It is hard for me to do this. I know what I want but lack the technical skill to do it. It is very frustrating. I have no idea what to do.
If someone can work it out and show me the code I can then understand it and use it elsewhere.
Here is an example of the next button to go to the next record if that helps.
private void btnNext_Click(object sender, EventArgs e)
{
if (inc != MaxRows - 1)
{
inc++;
NavigateRecords();
}
else
{
MessageBox.Show("You have reached the end of available items", "End of Available Items", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
Use data binding, instead of assigning values manually to controls.
create a model class
public class MyClass
{
public string Maker { get; set; }
public double price { get; set; }
// and so on, for all your fields
}
Add a object data source for MyClass in the "Data Sources" explorer in Visual Studio.
Drag the fields form the Data Sources to your form. Visual Studio automatically add a BindingSource and a BindingNavigator to your form.
Assign your data to the BindingSource in the form:
this.bindingSource1.DataSource = myData;
Where myData is some enumeration of MyClass objects.
You can do this for database sources as well. But personally I prefer to have my data in classes. Is's easier to handle, than either manipulating DataSets or form fields directly.
Based on your description, I think this is what you want
void btnNext_Click(object sender, EventArgs e) {
int id = Int32.Parse(yourIdTextBox.Text);
DataRow row = ds1.Tables["Laptops"].Rows.OfType<DataRow>()
.SingleOrDefault(r => (int)r.ItemArray[your id index] == id);
if (row == null)
{
//user typed in invalid row id
} else
processRow(row);
}
void processRow(DataRow row){
txtMaker.Text = row.ItemArray.GetValue(1).ToString();
txtModel.Text = row.ItemArray.GetValue(2).ToString();
txtPrice.Text = row.ItemArray.GetValue(3).ToString();
txtBids.Text = row.ItemArray.GetValue(4).ToString();
txtScreen.Text = row.ItemArray.GetValue(5).ToString();
txtCPU.Text = row.ItemArray.GetValue(6).ToString();
txtMemory.Text = row.ItemArray.GetValue(7).ToString();
txtHD.Text = row.ItemArray.GetValue(8).ToString();
picLaptops.Image = Image.FromFile(row.ItemArray.GetValue(9).ToString());
}
Which would then simplify your NavigateRecors() method to
private void NavigateRecords()
{
DataRow dRow = ds1.Tables["Laptops"].Rows[inc];
processRow(dRow);
}

Get value from programmatically created TextBox in C#

I got this itching problem and I cant get the code to work
How can i read the value from the TextBox when the form is posted?
Some code...
protected override void CreateChildControls() {
base.CreateChildControls();
TextBox queryBox = new TextBox();
queryBox.ID = "querybox";
queryBox.ToolTip = "Enter your query here and press submit";
Controls.Add(queryBox);
Button queryButton = new Button();
queryButton.UseSubmitBehavior = false;
queryButton.ID = "querybutton";
Controls.Add(queryButton);
if (Page.IsPostBack == true) {
try {
string query = querybox.Text;
DataGrid dataGrid = new DataGrid();
dataGrid.DataSource = Camelot.SharePointConnector.Data.Helper.ExecuteDataTable(query, connectionString);
dataGrid.DataBind();
Controls.Add(dataGrid);
} catch (Exception a) {
Controls.Add(new LiteralControl(a.Message));
} // try
} // if
} // void
I've shortened the code a bit but you see the idea, its the string query = querybox.text that wont work. I've tried with a few different variants, i.e.
TextBox querybox = (TextBox)FindControl("querybox");
string query = querybox.Text;
But no...
Any tips is appreciated!
Thanks
The problem is that your controls are not populated with values from the ViewState in CreateChildControls. I'd recommend using a click event handler on your button.
Update your button code:
Button queryButton = new Button();
queryButton.UseSubmitBehavior = false;
queryButton.ID = "querybutton";
queryButton.Text = "Query";
queryButton.Click += new EventHandler(queryButton_Click);
Controls.Add(queryButton);
Then, write the click event handler:
void queryButton_Click(object sender, EventArgs e)
{
TextBox querybox = this.FindControl("querybox") as TextBox;
try
{
string query = querybox.Text;
DataGrid dataGrid = new DataGrid();
dataGrid.DataSource = Camelot.SharePointConnector.Data.Helper.ExecuteDataTable(query, connectionString);
dataGrid.DataBind();
Controls.Add(dataGrid);
}
catch (Exception a)
{
Controls.Add(new LiteralControl(a.Message));
} // try
}
Try stepping through and looking into the Request.Form["name"] object.
What is probably happening is your Text box may not be being saved properly in the view state, but if it is a valid form object when a post back occurs it should exist within the Request.Form object, the ID may be different so you may have to do some searching.
Trikks,
I've found this which might help you.
Try looking for the text box in the load event (after checking its a postback!) rather than CreateChildControls which will separate your code out and make things a bit clearer. As Mmerrell says the id will probably get altered too, depending on the rest of the page.
You get the null reference exception because you do a
TextBox querybox = (TextBox)FindControl("querybox");
on the PAGE object.
So you're searching for page->querybox
But the textbox is in page->form1->querybox.
You need to write a recursive findcontrol, because querybox is a control in the form1 control, not a control in page.
public static Control FindControlRecursive(Control container, string name)
{
if ((container.ID != null) && (container.ID.Equals(name)))
return container;
foreach (Control ctrl in container.Controls)
{
Control foundCtrl = FindControlRecursive(ctrl, name);
if (foundCtrl != null)
return foundCtrl;
}
return null;
}
It might help to wrap the code in a !Page.IsPostBack check. Otherwise the textboxes get recreated on postback and delete any information.
if (!Page.IspostBack) {
TextBox queryBox = new TextBox();
queryBox.ID = "querybox";
queryBox.ToolTip = "Enter your query here and press submit";
Controls.Add(queryBox);
Button queryButton = new Button();
queryButton.UseSubmitBehavior = false;
queryButton.ID = "querybutton";
Controls.Add(queryButton);
} else {
try {
string query = querybox.Text;
DataGrid dataGrid = new DataGrid();
dataGrid.DataSource = Camelot.SharePointConnector.Data.Helper.ExecuteDataTable(query, connectionString);
dataGrid.DataBind();
Controls.Add(dataGrid);
} catch (Exception a) {
Controls.Add(new LiteralControl(a.Message));
} // try
} // if
Oh and don't trust the user to enter a query on your database.
Your database will crash and burn

Categories

Resources