Add dynamically text from textbox to table - c#

I have 3 TextBoxes for user input.
I want the user to enter name, email and age and then clicking on a button to put it into a table.
I have created it using design mode, but I have issues with the table, how should I create the table?
how can I make it create a new row and take the information from the textboxes to the right cells?
This is the code I`m trying to do:
public partial class WebForm1 : System.Web.UI.Page
{
Table myTable;
TableCell[] td;
TableRow tr;
protected void Page_Load(object sender, EventArgs e)
{
myTable = new Table();
}
protected void btnAdd_Click(object sender, EventArgs e)
{
for (int i = 1; i <= 1;i++ )
{
tr = new TableRow();
for(int j = 0; j <=3; j++)
{
td = new TableCell[3];
td[0].Text = txtName.Text;
td[1].Text = txtMail.Text;
td[2].Text = txtAge.Text;
tr.Cells.Add(td[j]);
}
}
myTable.Rows.Add(tr);
Panel1.Controls.Add(myTable);
}

Break down the problem into smaller pieces.
1) Creating the table
You said you already created "it". I don't know if you meant the text boxes or the table, but if you are already using design view, continue using it. There is a table control in the Toolbox you can drag onto the web page. Do that. Specify three columns and give them names.
2) Adding the inputs to the table
Don't worry about new rows yet. Just focus on getting the values in the text boxes into the first row of the table.
Double click the web page button. This should create code for a Click event. Here is where you add the code to copy the data from the boxes into the table. Something like :
`DataRow row = new DataRow();
row[0] = textboxName.Text;
row[1] = textboxEmail.Text;
row[2] = textboxAge.Text;
yourTable.Rows.Add(row);`
Obviously you want to replace the names here with whatever you named them.

Related

How to bind Access database to DataTable?

I'm new to C# and Visual Studio.
I'm working on a project that is searching through a database of information.
I want to bind a database (Microsoft access file) to my datagridview
but I want it to work with my preexisting code which utilizes a datatable converted into a dataview.
My database has a lot of information and I don't want to put it in manually. I've tried binding the information directly to the datagridview (through datasource in the properties) but then searching doesn't work**. I've looked into sql but im trying to avoid learning 2 languages at the same time.
My projects basic functionality contains: 1 combobox (idCbo) containing the search query's 1 datagridview for displaying the information
this setup is for searching one column only, im going to duplicate the code for the oher columns
The name of the column in the datagridview selects the column(id) for filtering then the combo box(idCbo) searches that column for matching characters in the datagridview and comboBox list.
the combo box contains the values 1-100 for searching the column
public partial class Form1 : Form
{
DataTable dt = new DataTable();
DataView dataView;
public Form1()
{
InitializeComponent();
dt.Columns.Add("id", typeof(int));
for (int i = 0; i < 100; i++)
dt.Rows.Add(i);
dataView = new DataView(dt);
this.dataGridView1.DataSource = dataView;
}
private void idCbo_SelectedIndexChanged(object sender, EventArgs e)
{
string query = idCbo.Text;
dataView.RowFilter = $"convert(id,'System.String') LIKE '%{query}%'";
}
}
**
Binding the database to the datagridview while using this code renders column titles but not the information and the code cannot access the database, columns or the rows System.Data.EvaluateException: 'Cannot find column ...
Big thanks to Johng for assisting me with the code :)
CURRENT WORKING CODE
public Form1()
{
InitializeComponent();
}
public static BindingSource gridBindingSource;
private void idCbo_SelectedIndexChanged(object sender, EventArgs e)
{
string query = idCbo.Text;
gridBindingSource = (BindingSource)dataGridView1.DataSource;
if (gridBindingSource != null)
{
if (query == "All")
{
gridBindingSource.Filter = "";
}
else
{
gridBindingSource.Filter = "convert(id,'System.String') LIKE '%" + query + "%'";
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the '_InfoFinalv_2___CopyDataSet.Info' table. You can move, or remove it, as needed.
infoTableAdapter.Fill(this._InfoFinalv_2___CopyDataSet.Info);
idCbo.Items.Add("All");
for (int i = 1; i < 100; i++)
{
idCbo.Items.Add(i);
}
idCbo.SelectedIndex = -1;
}
private void idReset_Click(object sender, EventArgs e)
{
idCbo.SelectedIndex = -1;
}
If you have set up the grids data source in the designer “correctly” then using the DataView as you want can be simplified by using the existing BindingSource that is usually created when you set up the grid’s data source in the designer.
We can use the existing grid’s BindingSource and then use it’s Filter property as opposed to converting the BindingSource to a DataView to filter. This will allow us to set the filter in the grid WITHOUT having to “change” the grids data source.
Remove all the code you have in the form constructor obviously leaving the InitializeComponent(); and add the code below to the forms Load event. In the load event all we do is set up the combo box with the proper values. I added an “All” option to allow the user to “un-filter” the data in the grid.
private void Form1_Load(object sender, EventArgs e) {
// TODO: This line of code loads data into the 'database1DataSet.EmployeeDT' table. You can move, or remove it, as needed.
employeeDTTableAdapter.Fill(this.database1DataSet.EmployeeDT); // <- created by the designer
idCbo.Items.Add("All");
for (int i = 1; i < 100; i++) {
idCbo.Items.Add(i);
}
idCbo.SelectedIndex = 0;
}
Then in the combo boxes SelectedIndexChanged event... change the code as shown below. Cast the grids DataSource to a BindingSource and then use its Filter property.
private void idCbo_SelectedIndexChanged(object sender, EventArgs e) {
string query = idCbo.Text;
BindingSource GridBS = (BindingSource)dataGridView1.DataSource;
if (GridBS != null) {
if (query == "All") {
GridBS.Filter = "";
}
else {
GridBS.Filter = "EmpID LIKE '%" + query + "%'";
}
}
}
Here's the tip:
On the form load, make an ajax call to the database and fetch only the required data columns. Return data will be in JSON that can be used as data for DataTable.
I used it in an MVC project recently and it works fine. If you would like I can share the detailed code and logic.
Not sharing the code since I'm not sure if you are on .Net MVC.

How to dynamically filter DataGridView using TextBox data?

I created a simple DataGridViewa with a single column and added a TextBox above.
Currently the text actually a DataTable (I though this would make things easier for filtering) with 2 columns, number and text (I hide the number in the DataGridView ). I can change it to any other class if required.
When the user enters a letter in the TextBox, I want to dynamically filter and show only the lines containing this text.
I load the data to the DataGridView like this:
private void PhrasesForm_Load(object sender, EventArgs e)
{
phrasesDataGridView.ReadOnly = true;
phrasesDataGridView.DataSource = _phrases.Phrases;
phrasesDataGridView.Columns[0].Visible = false;
this.phrasesDataGridView.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
When add another letter the filter will be readjusted.
What do I write here...
private void filterBox_TextChanged(object sender, EventArgs e)
{
}
If you have a DataGridView, or any Control with a DataSource, consider using Nuget Package BindingListView. It has functionality to sort the binding list by any column on a mouse click, but it also has functionality to filter the data.
List<Customer> customers = ...
BindingListView<Customer> customerView = new BindingListView<Customer>(customers);
dataGridView1.DataSource = customerView;
And presto, if shows all Customers. The columns depend on you column definition.
To filter the customers, for instance, show only customers with born before a certain date:
void ShowCustomers(DateTime limitDate)
{
customerView.ApplyFilter( customer => customer.BirthDay < limitDate));
}
Result: only the older Customers are shown.
You can do it similarly:
void ShowItemsWithPhraseStart(string phraseStart)
{
myView.ApplyFilter(row => row.Phrase.StartsWith(phraseStart));
}
And bingo: the datagrid shows only the row with a value for property Phrase that starts with phraseStart.
private void OnTextBocChanged(object sender, ...)
{
var text = this.TextBox1.Text;
ShowItemsWithPhraseStart(text);
}

Pushing values from DataView built on one Windows Form to another Windows Form

I have 2 windows forms. One form with datagridview and button, and the other form with labels. More or less like Master-Detail design. I have 2 related tables in database. I can fill the datagridview nicely with data from the main table. First I select data on datagridview, and I want to use the button to display the values on the labels located on another form.
Once data is loaded on datagridview; I use the following code for the methods to filter the underlying tables based on selection made from datagridview:
[form 2]
public DataView EnterpriseView()
{
foreach (DataGridViewRow row in Viewer.SelectedRows)
identifier = row.Cells["BusinessName"].Value.ToString();
var EnterpriseVw = new DataView(EnterpriseDT)
{
RowFilter = "BusinessName = '" + identifier + "'"
};
return EnterpriseVw;
}
After returning the view, I want to use the button to push the information to another form that has the labels. I'm not sure about how to get this working. I tried different codes of my own, and it doesn't work
My issue how to code the button_click event. And is there another event I need to call for this to work? How does the button know if I have selected something on the datagridview? How does the datagridview know I have clicked the button? I tied something like this for the button:
[form 2]
private void button1_Click(object sender, EventArgs e)
{
index = Viewer.SelectedRows[0].Index;
Viewer.Rows[index].Selected = true;
//EnterpriseView();
//DetailsView();
//this.Click += new EventHandler(Viewer_SelectionChanged);
if (Viewer.Rows[index].Selected == true)
{
var frm1 = new form1(); //form with labels
//foreach(DataGridViewRow row in Viewer.SelectedRows)
frm1.Publish(); //method that assigns data to labels
}
It doesn't work
I tried using somthing like this for the labels:
[form 1]
public void Publish()
{
var frm2 = new form2();
var vEnterprise = frm2.EnterpriseView();
Email.DataBindings.Add("Text", vEnterprise, "EmailAddress");
}
To Get values from Selected Row of the DataGridView you need to change some properties :
First You need to set SelectionMode to FullRowSelect.
Second You need to set MultiSelect to False.
You can do it through the properties tab.
Then we can use dataGridView1.SelectedRows it will return DataGridViewSelectedRowCollection a list of the selected rows, but since we disabled multiSelect there will always be just one so we can use [0].
Now in the Button_click event Handler
private void button1_Click(object sender, EventArgs e)
{
// To Get The Selected Row
var dr = dataGridView1.SelectedRows[0];
// The Cells Property is going to return DataGridViewCellCollection a list again
// Basically the columns so the first one will be the first column and so on
string item1 = dr.Cells[0].Value.ToString();
string item2 = dr.Cells[1].Value.ToString();
string item3 = dr.Cells[2].Value.ToString();
}
In the Form with the labels Define a second constructor.
Say we Have 3 Labels
We gonna define a second constructor that takes 3 Strings, Like this
public TheSecondForm(String S1, String S2,String S3)
{
label1.Text = S1;
label2.Text = S2;
label3.Text = S3;
}
Then The button Event Handle will become like this :
private void button1_Click(object sender, EventArgs e)
{
var dr = dataGridView1.SelectedRows[0];
string item1 = dr.Cells[0].Value.ToString();
string item2 = dr.Cells[1].Value.ToString();
string item3 = dr.Cells[2].Value.ToString();
// What was added
TheSecondForm frm2 = new TheSecondForm(item1, item2, item3);
frm2.Show();
}
By Now the labels will be populated.

Dynamic Button not triggered in ASP.Net from static class

I am trying to make a dynamic table which has a couple of rows and the last row is a plus button, which will add a new row. (I will only describe the important information, to keep it simple.)
I thought of this way to accomplish it:
// .aspx code
<li><asp:LinkButton ID="LM_Show" runat="server" Text="Show list" OnClick="Action"/></li>
<asp:PlaceHolder ID="infoTable" runat="server"></asp:PlaceHolder>
//CreateTable function
public void Clicked(object sender, EventArgs e){
table();
}
public void table() {
//Do stuff...
//Screen variable is keeping track of which screen should be shown in .aspx
infoTable.Controls.Add(CreateView.createTable<Employee>(screen, this.Context, table));
}
//Create the actual table
public static Table createTable<T>(Screen screen, HttpContext context, Action method) where T : new() {
//New table and make it stretch
Table tb = new Table();
tb.Width = Unit.Percentage(100);
tb.Height = Unit.Percentage(100);
//Gather list from session
List<T> items = (List<T>)context.Session["list"];
//Create table content based on the list
for (int i = 1; i <= items.Count(); i++) {
TableRow tr = new TableRow();
//Foreach property create cells with content according to the property
//Add these cells to the row
tb.Rows.Add(tr);
}
//Create 1 final row which has a button to be able to add 1 row
TableRow tr2 = new TableRow();
TableCell tc = new TableCell();
tr.Cells.Add(tc);
//Create the Button
Button button = new Button();
button.Text = "+";
//!!This is not getting triggered!!//
button.Click += (s, e) => {
List<T> tempItems = (List<T>)context.Session["list"];
tempItems.Add(new T());
context.Session["list"] = tempItems;
//When a button is pressed, it gives a postback.
//The table has to be rebuild over again with the newly added item
method();
};
//!!This is not getting triggered!!//
//Add the button
tr2.Cells[0].Controls.Add(button);
tb.Rows.Add(tr2);
return tb;
}
Any comments about the code or how to accomplish it even better are also very welcome.
This could be achieved more easily if you used jQuery AJAX and communicate with a web service/method to get the data. However, it can be achieved in C# as well. Assuming that the given below part of the code is not working,
//Add the button
tr2.Cells[0].Controls.Add(button);
tb.Rows.Add(tr2);
You can try adding button to tc first, and then add tc to the row tr
tc.Controls.Add(button);
tr2.Cells.Add(tc);
tb.Rows.Add(tr2);
Good Luck!

How to find index of a control in a placeholder

I have the following code :
Label docsLabel = new Label();
docsLabel = (Label)tasksPlaceholder.FindControl("taskdocs_" + taskId);
int index = tasksPlaceholder.Controls.IndexOf(docsLabel);
The label is found within the placeholder, but when I call .IndexOf() it always returns -1.
How do I find the correct position of this control?
This is an important information in your comments:
the element I want to update is 3 levels down (TableRow -> TableCell ->Label)
Control.FindControl finds all control in this NamingContainer whereas ControlCollection.IndexOf finds only controls in this control. So if this control contains for example a table which contains rows and cells and every cell contains also controls, all of these controls will not be found by IndexOf, only the top-control is searched.
Control.FindControl will search all controls that belong to this NamingContainer(a control that implements INamingContainer). A table/row/cell does not implement it, that's why all of these controls are also searched with FindControl.
However, FindControl will not search through sub-NamingContainers (like a GridView in a GridViewRow).
This reproduces your issue:
protected void Page_Init(object sender, EventArgs e)
{
// TableRow -> TableCell ->Label
var table = new Table();
var row = new TableRow();
var cell = new TableCell();
var label = new Label();
label.ID = "taskdocs_1";
cell.Controls.Add(label);
row.Cells.Add(cell);
table.Rows.Add(row);
tasksPlaceholder.Controls.Add(table);
}
protected void Page_Load(object sender, EventArgs e)
{
Label docsLabel = (Label)tasksPlaceholder.FindControl("taskdocs_1");
int index = tasksPlaceholder.Controls.IndexOf(docsLabel);
// docsLabel != null and index = -1 --> quod erat demonstrandum
}
How do I find the correct position of this control?
If you want to find the row-number this label belongs to:
Label docsLabel = (Label)tasksPlaceholder.FindControl("taskdocs_1");
TableRow row = (TableRow)docsLabel.Parent;
Table table = (Table)row.Parent;
int rowNumber = table.Rows.GetRowIndex(row);

Categories