Select row from DataGridView and place it in a textbox - c#

I have a windows form application which has a datagridview to display a menu full of meals.
I want to be able to allow the user to choose a seat number and then select a row and once the row is selected all the information in that row to be put in the available textbox below which will then be submitted in a new xml file titled order.xml.
So far I have the the saving to the xml part sorted, but I can't seem to get the datagridview task done.
Code to save the data in the order.xml file.
XDocument doc = XDocument.Load("order.xml");
XElement root = new XElement("MenuInfo");
root.Add(new XElement("Data1", dataGridView.DataSource));
root.Add(new XElement("Data2", _seat));
root.Add(new XElement("Data3", buttonTable1.Text));
root.Add(new XElement("Data4", lbPrice.Text));
doc.Element("Menu").Add(root);
doc.Save("order.xml");
MessageBox.Show("The order has been placed.");

You can react on the RowEnter-Event, which fires if the user enter a row. Do following then:
private void dataGridView1_RowEnter(object sender, System.Windows.Forms.DataGridViewCellEventArgs e)
{
var yourGrid = sender as DataGridView;
if (yourGrid != null)
{
var row = yourGrid.Rows[e.RowIndex].DataBoundItem as DataRowView;
if (row != null)
{
//Here you have access to the actual row.
//So simply get the string foreach column you need
string myStringForTextEdit = Convert.ToString(row["MealID"]) + Convert.ToString(row["Food"]) +
Convert.ToString(row["Price"]) + Convert.ToString(row["Time"]) +
Convert.ToString(row["Quantity"]);
myTextEdit.Text = myStringForTextEdit;
}
}
}
This simple example use the RowEnter-Event gets the current row and build a string based on all row Values.
I hope this helps.

Related

How to get a ComboBox in a DataGridViewCell to drop down after a single click?

I have a DataGridView which has it's first column's style set to a ComboBox rather than the default TextBox. Since the number of rows in the DataGridView is not fixed on startup I cannot load in data to the ComboBoxes for each row when a new row is added. So I tried loading on the event of a user adding a row to the DataGridView:
public void myDataGridView_UserAddedRow(object sender, DataGridViewRowEventArgs e)
{
// Identifiers used are:
var myTableAdapter = new databaseTableAdapters.myTableTableAdapter();
var myDataTable = myTableAdapter.GetData();
int rowIndex = myDataGridView.CurrentcellAddress.Y;
var comboBoxCell = (DataGridViewComboBoxCell)myDataGridView.Rows[rowIndex].Cells[0];
string itemToAdd;
// Load in the data from the data table
foreach (System.Data.DataRow row in myDataTable.Rows)
{
// Get the current item to be added
itemToAdd = row[0].ToString();
// Make sure there are no duplicates
if (!comboBoxCell.Items.Contains(itemToAdd))
{
comboBoxCell.Items.Add(itemToAdd)
}
}
}
but this only will allow the user to see the drop down options after a second click. I would like to be able to have the user only click on the combo box once and see the options rather than the less intuitive double click. How can this be done?
The cell must gain focus for the drop down to occur, so the double click is actually a single click to gain focus on that cell and the second click is what causes the drop down to occur. So to see how to change focus following this link. I was able to modify the code with a single line of code
public void myDataGridView_UserAddedRow(object sender, DataGridViewRowEventArgs e)
{
// Identifiers used are:
var myTableAdapter = new databaseTableAdapters.myTableTableAdapter();
var myDataTable = myTableAdapter.GetData();
int rowIndex = myDataGridView.CurrentcellAddress.Y;
var comboBoxCell = (DataGridViewComboBoxCell)myDataGridView.Rows[rowIndex].Cells[0];
string itemToAdd;
// Load in the data from the data table
foreach (System.Data.DataRow row in myDataTable.Rows)
{
// Get the current item to be added
itemToAdd = row[0].ToString();
// Make sure there are no duplicates
if (!comboBoxCell.Items.Contains(itemToAdd))
{
comboBoxCell.Items.Add(itemToAdd)
}
}
// Send the focus to the next combo box (removes need for a double click)
myDataGridView.CurrentCell = myDataGridView.Rows[rowIndex + 1].Cells[0]; // <--- HERE
}

Not able to find embedded control in gridview

I have a gridview and on some condition basis, I am inserting text box in it in RowDataBound:
private void GetColumnWithValidation(GridViewRowEventArgs e, string columnName, int columnLength)
{
if (Convert.ToString(DataBinder.Eval(e.Row.DataItem, columnName)).Length > columnLength)
{
int colindex = GetColumnIndexByName(e.Row, columnName);
TextBox txt = new TextBox();
txt.Text = Convert.ToString(DataBinder.Eval(e.Row.DataItem, columnName));
txt.BorderColor = Color.Red;
txt.ID = "txt_" + i + "_" + colindex;
lstErrorTracker.Add(i + "_" + colindex);
//link.NavigateUrl = Convert.ToString(DataBinder.Eval(e.Row.DataItem, "PV_INVOICE_LOCATION"));
e.Row.Cells[GetColumnIndexByName(e.Row, columnName)].Controls.Add(txt);
}
}
Now if I change some data in text box of gridview I want that to be fetch whenever I click Update button. Update button is placed outside of gridview as a normal asp.net button.
But when I am trying to fetch the data I am getting null.
foreach (GridViewRow row in GVUploadDetails.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
TextBox txt= (row.Cells[3].FindControl("txt_0_3") as TextBox);
var test = txt.Text;
}
}
I am getting text data as null. Please help how to get those values. And on other hand I want the entire data of the gridview as a Dataset or datatable how can I get that.
The NamingContainer is the GridViewRow not the cell, so you should use:
foreach (GridViewRow row in GVUploadDetails.Rows)
{
TextBox txt = row.FindControl("txt_0_3") as TextBox;
// ...
}
If this doesn't fix the issue, where in the page's life-cycle do you addd this TextBox programatically? You know that you always have to re-create it on every consecutive postback? Do that latest in Page_Load, better Page_Init.
If you add it from RowDataBound you have to re-create it in RowCreated, otherwise it's too late to retain the ViewState.

ASP.NET GridView update Source but not commands

I have a gridview. Its datasource is taken from XML by adding some xmlElemens in a list and than set the list as its data source. Now I am implementing a search feature.
So I am filtering the list in this way:
protected void btnSearch_Click(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load(prog); //Percorso file xml
List<string> nomi = new List<string>();
XmlElement root = doc.DocumentElement;
XmlNodeList elemLists = root.GetElementsByTagName("nome");
// this binds the gridview to the title text to display
for (int i = 0; i < elemLists.Count; i++)
{
if(elemLists[i].InnerXml.ToString().ToLower().StartsWith(txtSearchMaster.Text.ToLower()) ||
elemLists[i].InnerXml.ToString().ToLower() == txtSearchMaster.Text.ToLower() ||
elemLists[i].InnerXml.ToString().ToLower().EndsWith(txtSearchMaster.Text.ToLower()) ||
elemLists[i].InnerXml.ToString().ToLower().Contains(txtSearchMaster.Text.ToLower()))
nomi.Add(elemLists[i].InnerXml.ToString());
}
GridView1.DataSource = nomi.OrderBy(q => q).ToList();
GridView1.DataBind();
}
The data is shown correctly but the problem is that when I click the button next the column that is auto generated and get the cell content (that is an element of the list) it return the content of the cell at the same index but of the previous data.
How can I overcome to this?
The problem here is that your "filter" as it were is only applied on the search click. If you had hidden state where a search term was stored, and applied it on every postback, if the state exists, then clicking your grid button would work.
<asp:HiddenField ID="SearchString" runat="server" value="" />
and in your btnSearch_Click
SearchString.Value = txtSearchMaster.Text.ToLower().Trim();
and then add the filter logic in Page_Load
if (IsPostBack) {
// filter on hidden value if not empty.
if (!String.IsNullOrEmpty(SearchString.Value)) {
// filter here
}
}
Just fixed by adding
if (!IsPostBack)
{
...
}
in Page_Load and leaving the filter login into the search button click method.

C# View tables in datagridview based upon combobox item selection

I want to load tables from database in datagridview based upon selected combobox item. I'm using entity framework. My code is as follows:
private void btnCRUDLoadTable_Click(object sender, EventArgs e)
{
//prompt user when "Load Table" button is clicked without selecting any database or table or user
if (cboSelectDB.SelectedIndex <= -1 || cboSelectUser.SelectedIndex <= -1 || cboSelectTable.SelectedIndex <= -1)
{
MessageBox.Show("Please Select Database, User and Table First");
}
else
{
//load data according to combobox selection in datagridview
if (cboSelectUser.Text.ToString() == "User_name")
{
var context = new NameEntities();
BindingSource bi = new BindingSource();
//here, instead of putting tablename is there a way to put
//combox item name? I have tried combobox.Text.ToString(),
//but it doesn't work, shows error
bi.DataSource = context.TableName;
dgvLoadTable.DataSource = bi;
dgvLoadTable.Refresh();
}
}
}
Any help will be appreciated, thanks.
You can use reflation to set the table name dynamically. As below.
var context = new NameEntities();
BindingSource bi = new BindingSource();
//here, instead of putting tablename is there a way to put
//combox item name? I have tried combobox.Text.ToString(),
//but it doesn't work, shows error
var TableName = combobox.Text.ToString();
bi.DataSource = context.GetType().GetProperty(TableName).GetValue(obj, null);
dgvLoadTable.DataSource = bi;
dgvLoadTable.Refresh();
The TableName must be the property name created in NameEntities corresponding to the database table.

Accessing nested DataGridview via Parent/ TabControl->TabPage

Im currently creating a Windows Form Application where I want to get data from a database that will be synchronized to as many target databases that I can find in a specific table.
To do so, I made a TabControl inside my Form 1 with TabPages created pragmatically for every target db. For each TabPage I create a DataGridview to store the data and I let the user select the records they want to synchronize.
foreach (DataRow row in targetDatabases.Rows)
{
//Checking for target databases that aren't Master
if (int.Parse(row["IS_MASTER"].ToString()) == 0)
{
//Creating a new TabPage for every target found in the Table
TabPage newPage = new TabPage(row["CODE"].ToString());
// I'm not sure if this should be
newPage.Parent = tabControl;
// or tabControl.Controls.Add(newPage)
//Creating a new DataGridView for every target found
DataGridView newDgv = new DataGridView();
//Also not sure if this should be
newDgv.Parent = newPage;
//or newPage.Controls.Add(newDgv)
//Setting the DataSource
currDGV.DataSource = Model.getGridViewData(xmlpath, 0);
//Layout settings for the DataGridView
.
.
.
}
}
// Return the TabControl to the View
return tabControl;
No problem untill now.
Now the user can select which records he wants to be synchronized and to which target.
This is what it looks like:
But now, I don't know how to access the data in each DataGridView to save the users selection to a file or to start the synchronization.
I tried something like this:
for (int i = 0; i < targetDatabaseCount; i++)
{
tabPages[targetDatabaseCount] = (TabPage)inputTabControl.GetControl(targetDatabaseCount);
foreach (TabPage tabPage in tabPages)
{
DataGridView tempDgv = //don't know how to get the gridview from the TabPage
}
}
Please be lenient with me as I am an apprentice and this is my first post here :)
You could iterate the controls in each tab page and if the control is datagridview you could cast it and use.
Like this:
foreach (TabPage tbp in tbctrl.TabPages)
{
foreach (Control ctrl in tbp.Controls)
{
if (ctrl is DataGridView)
{
DataGridView newDgv = (DataGridView)ctrl;
string strValue = newDgv.Rows[0].Cells[0].Value.ToString();
}
}
}

Categories