I have a Data grid view in which I have changed all the cells to text boxes to allow for a bulk update. The problem is that the users new input values are not registering and instead the cells are holding the old values. I taught it might be to do with a post back issue but cant imagine it is as there is no loading of old data in the page load. I also considered that the text boxes might not be registering properly because they are added without an ID but not to sure on that.
Changed cells to textboxes here.
foreach (GridViewRow row in GridView1.Rows)
{
for (int i = 4; i < row.Cells.Count; i++)
{
TextBox test = new TextBox();
test.Text = row.Cells[i].Text.ToString();
row.Cells[i].Controls.Add(test);
}
}
trying to pull new values and them to list newValues here
foreach(GridViewRow row in GridView1.Rows) {
if (row.RowType == DataControlRowType.DataRow) {
bool isChecked = row.Cells[0].Controls.OfType < CheckBox > ().FirstOrDefault().Checked;
if (isChecked) {
string table = DropDownList1.Text.ToString();
List < string > selectedValues = CheckBoxList1.Items.Cast < ListItem > ()
.Where(li = > li.Selected)
.Select(li = > li.Value)
.ToList();
List < string > newValues = new List < string > ();
int userid = Convert.ToInt32(row.Cells[1].Text.ToString());
//GridViewRow row = (GridViewRow)GridView1.Rows[e.RowIndex];
Label lblID = (Label) row.FindControl("WDB_Id");
//TextBox txtname=(TextBox)gr.cell[].control[];
for (int i = 4; i < selectedValues.Count + 4; i++) {
newValues.Add(row.Cells[i].Text.ToString());
}
}
}
}
Thanks
Related
hello experts help please, i have two form in my project and one of those form1 have dataGridView and i want to update the gridview according to text value from form 2,
i had done updating dgv but all row updated on button click event
ex. i have 4 rows different description and cell value after click event
all those 4 rows updating to 1 value.
Form 1
dgv cellmouseclick event
if (e.RowIndex >= 0)
{
DataGridViewRow row = dataGridView2.Rows[e.RowIndex];
_choosenPart = row.Cells[0].Value.ToString();
_choosenQty = row.Cells[2].Value.ToString();
_choosenPrice = row.Cells[4].Value.ToString();
_choosenAmount = row.Cells[5].Value.ToString();
_choosenTotal = row.Cells[7].Value.ToString();
}
FrM_Edit EditGV = new FrM_Edit(this);
EditGV.Show();
In form 2
//constructor
Form F2_main = null;
public FrM_Edit(Form DgVForm1)
{
F2_main=DgVForm1;
InitializeComponent();
}
button click event
r2main_choosenPart = textBox1.Text;
r2main_choosenQty = textBox2.Text;
r2main_choosenPrice = textBox3.Text;
r2main_choosenAmount = textBox4.Text;
r2main_choosenTotal = textBox5.Text;
DataGridView Main_dg = (DataGridView)F2_main.Controls["dataGridView2"];
for (int i = 0; i < Main_dg.Rows.Count; i++)
{
Main_dg.Rows[i].Cells[0].Value = r2main_choosenPart;
Main_dg.Rows[i].Cells[2].Value = r2main_choosenQty;
Main_dg.Rows[i].Cells[4].Value = r2main_choosenPrice;
Main_dg.Rows[i].Cells[5].Value = r2main_choosenAmount;
Main_dg.Rows[i].Cells[7].Value = r2main_choosenTotal;
}
this.Close();
//this for loop takes all rows of your DataGridView. And it is normal that you see that all rows are changing because for all rows, you apply the same code.
DataGridView Main_dg = (DataGridView)F2_main.Controls["dataGridView2"];
for (int i = 0; i < Main_dg.Rows.Count; i++)
{
Main_dg.Rows[i].Cells[0].Value = r2main_choosenPart;
Main_dg.Rows[i].Cells[2].Value = r2main_choosenQty;
Main_dg.Rows[i].Cells[4].Value = r2main_choosenPrice;
Main_dg.Rows[i].Cells[5].Value = r2main_choosenAmount;
Main_dg.Rows[i].Cells[7].Value = r2main_choosenTotal;
}
Instead, you should update only the row that you want to updaate.
You can use differents methods.
For exemple:
for (int i = 0; i < Main_dg.Rows.Count; i++)
{
if( Main_dg.Rows[i].Cells[0].Value == "valueToChange") //Checking an ID or other value.
{
Main_dg.Rows[i].Cells[0].Value = r2main_choosenPart;
Main_dg.Rows[i].Cells[2].Value = r2main_choosenQty;
Main_dg.Rows[i].Cells[4].Value = r2main_choosenPrice;
Main_dg.Rows[i].Cells[5].Value = r2main_choosenAmount;
Main_dg.Rows[i].Cells[7].Value = r2main_choosenTotal;
break; // To break after finding the row that you are looking for.
}
}
Or
for (int i = 0; i < Main_dg.Rows.Count; i++)
{
if(i == 2) //to update the third row of the grid.
{
Main_dg.Rows[i].Cells[0].Value = r2main_choosenPart;
Main_dg.Rows[i].Cells[2].Value = r2main_choosenQty;
Main_dg.Rows[i].Cells[4].Value = r2main_choosenPrice;
Main_dg.Rows[i].Cells[5].Value = r2main_choosenAmount;
Main_dg.Rows[i].Cells[7].Value = r2main_choosenTotal;
break; // To break after finding the row that you are looking for.
}
}
Or you can use your DataGridViews selected row to update.
I am trying to scrape data from the webpage. However, I am having a trouble scraping all of data in the table. I need to switch pages to get all the data and I am willing to get an output with DataGridTable. I am having a trouble figuring out how to do this even though there is a change with number of pages they have in the website. I would like to add information automatically on a data grid table pages by pages. My input(Website) is only showing 25 items. Thats why I have 25 items in DataGridTable. I would like to justify a "number of pages" from "go to end page button"'s element. So that my program knows how many pages are there to scrape from the website. but, if there's a different way, I wanna know thank you.
This is my code for now.
DataTable dt = new DataTable();
var header = driver.FindElement(By.CssSelector("#gridComponent > div.k-grid-header"));
foreach (var row in header.FindElements(By.TagName("tr")))
{
//Configure Number of Col and row
int cellIndex = 0;
string[] arr = new string[32];
//Get Cell Data
foreach (var cell in row.FindElements(By.TagName("th")))
{
// Check the header cell for a checkbox child. If no
// such child exists, add the column.
var headerCheckboxes = cell.FindElements(By.CssSelector("input[type='checkbox']"));
if (headerCheckboxes.Count == 0)
{
//Number of Col Data Load
if (cellIndex <= 29)
{
arr[cellIndex] = cell.Text;
dt.Columns.Add(cell.Text);
}
else
cellIndex++;
}
}
Console.WriteLine(arr);
}
var table = driver.FindElement(By.CssSelector("#gridComponent"));
//Get Row value
foreach (var row in table.FindElements(By.TagName("tr")))
{
//Configure Number of Col and row
int cellIndex = 0;
// Use a list instead of an array
List<string> arr = new List<string>();
//Get Cell Data
foreach (var cell in row.FindElements(By.TagName("td")))
{
// Skip the first column in the row by checking
// if the cell index is 0.
if (cellIndex != 0)
{
string cellValue = "";
Console.WriteLine(cell);
var checkboxes = cell.FindElements(By.CssSelector("input[type='checkbox']"));
if (checkboxes.Count > 0)
{
bool isChecked = false;
isChecked = checkboxes[0].Selected;
cellValue = isChecked.ToString();
}
else
{
cellValue = cell.Text;
}
arr.Add(cellValue);
}
cellIndex++;
}
dt.Rows.Add(arr.ToArray());
}
dataGridView1.DataSource = dt;
driver.FindElement(By.CssSelector("#gridComponent > div.k-pager-wrap.k-grid-pager.k-widget.k-floatwrap > ul > li:nth-child(3)")).Click();
}
This is the table that I am trying to scrape from.
This is the code for the following element that is shown picture above.
<span class="k-icon k-i-arrow-end-right"></span>
Thank you so much.
You may want to consider the index information "1 - 25 out of 64 items", since it is a good indicator of the total number of pages.
Batch = 1 - 25 i.e. 25 items per page
Total items = 64
No. of pages = roundup (64 / 25)
PS: A better option, without any computations, maybe to get the "data-page" attribute of the last page button.
I Finally got the answer for this.
private List<List<string>> GetRecords(IWebElement table)
{
List<List<string>> rows = new List<List<string>>(); ;
//Get Row value
foreach (var row in table.FindElements(By.TagName("tr")))
{
//Configure Number of Col and row
int cellIndex = 0;
// Use a list instead of an array
List<string> cols = new List<string>();
//Get Cell Data
foreach (var cell in row.FindElements(By.TagName("td")))
{
// Skip the first column in the row by checking
// if the cell index is 0.
if (cellIndex != 0)
{
string cellValue = "";
Console.WriteLine(cell);
var checkboxes = cell.FindElements(By.CssSelector("input[type='checkbox']"));
if (checkboxes.Count > 0)
{
bool isChecked = false;
isChecked = checkboxes[0].Selected;
cellValue = isChecked.ToString();
}
else
{
cellValue = cell.Text;
}
cols.Add(cellValue);
}
cellIndex++;
}
rows.Add(cols);
}
return rows;
}
private void button1_Click(object sender, EventArgs e)
{
//Configure to Hide CMD
var chromeDriverService = ChromeDriverService.CreateDefaultService();
chromeDriverService.HideCommandPromptWindow = true;
//Configure to Hide Chrome
ChromeOptions option = new ChromeOptions();
option.AddArgument("--headless");
//HIDING CHROME UN-COMMNET THE SECOND ONE TO SHOW
//IWebDriver driver = new ChromeDriver(chromeDriverService, option);
IWebDriver driver = new ChromeDriver();
driver.Url = "**************";
driver.Manage().Window.Maximize();
driver.SwitchTo().DefaultContent();
//Log-in
driver.FindElement(By.Id("username")).SendKeys("*****");
driver.FindElement(By.Id("password")).SendKeys("******" + OpenQA.Selenium.Keys.Enter);
//Entering Access Code
driver.FindElement(By.Id("password")).SendKeys("*******");
driver.FindElement(By.Id("accesscode")).SendKeys("********" + OpenQA.Selenium.Keys.Enter);
//go to CustomerList
driver.Navigate().GoToUrl("***********");
driver.Navigate().GoToUrl("*****************");
//Wait till load 3 seconds
waitOnPage(2);
DataTable dt = new DataTable();
var header = driver.FindElement(By.CssSelector("#gridComponent > div.k-grid-header"));
foreach (var row in header.FindElements(By.TagName("tr")))
{
//Configure Number of Col and row
int cellIndex = 0;
string[] arr = new string[32];
//Get Cell Data
foreach (var cell in row.FindElements(By.TagName("th")))
{
// Check the header cell for a checkbox child. If no
// such child exists, add the column.
var headerCheckboxes = cell.FindElements(By.CssSelector("input[type='checkbox']"));
if (headerCheckboxes.Count == 0)
{
//Number of Col Data Load
if (cellIndex <= 29)
{
arr[cellIndex] = cell.Text;
dt.Columns.Add(cell.Text);
}
else
cellIndex++;
}
}
Console.WriteLine(arr);
}
var table = driver.FindElement(By.CssSelector("#gridComponent"));
List<List<string>> records = GetRecords(table);
// Supposing you want the footer information
var lastPageStr = table.FindElement(By.ClassName("k-pager-last")).GetAttribute("data-page");
var lastPage = Convert.ToInt16(lastPageStr);
// You can select other info lik this
// class="k-link k-pager-nav" data-page="1"
driver.FindElement(By.CssSelector("#gridComponent > div.k-pager-wrap.k-grid-pager.k-widget.k-floatwrap > ul > li:nth-child(3)")).Click();
// Cycle over the pages
for (int p = 0; p < (lastPage - 1); p++)
{
driver.FindElement(By.CssSelector("#gridComponent > div.k-pager-wrap.k-grid-pager.k-widget.k-floatwrap > a:nth-child(4) > span")).Click();
waitOnPage(2);
var rows = GetRecords(table);
records.AddRange(rows);
}
// Add all rows to DT
//dt.Rows.Add(records[4].ToArray());
foreach(var row in records)
{
dt.Rows.Add(row.ToArray());
}
dataGridView1.DataSource = dt;
}
Currently I try to use Repeater WebControl in order to display a table that list out all possible component. Below is my table;
Right now I try to merged cells in Group Code and Group Description column that have the same value. Below is my merging cell code, noted that the code is in class;
public void repeaterRowSpan(string repeaterID, string columnID)
{
var pageHandler = HttpContext.Current.CurrentHandler;
Control ctrl = ((Page)pageHandler).Master.FindControl("ContentPlaceHolder3").FindControl(repeaterID);
Repeater repeaterName = (Repeater)ctrl;
for (int i = repeaterName.Items.Count - 1; i > 0; i--)
{
HtmlTableCell oCell_previous = (HtmlTableCell)repeaterName.Items[i - 1].FindControl(columnID);
HtmlTableCell oCell = (HtmlTableCell)repeaterName.Items[i].FindControl(columnID);
oCell.RowSpan = (oCell.RowSpan == -1) ? 1 : oCell.RowSpan;
oCell_previous.RowSpan = (oCell_previous.RowSpan == -1) ? 1 : oCell_previous.RowSpan;
if (oCell.InnerText == oCell_previous.InnerText)
{
oCell.InnerText = "";
oCell_previous.RowSpan += oCell.RowSpan;
}
}
}
Somehow the code manage to delete the same value in the column but maintain the rowspan. When I debugged, the oCell_previous.RowSpan return '2' so the code itself working fine. Below is the result of merging;
How can I modified my code in such way it will merged the cell?
In your opinion, between Repeater and GridView which is most suitable to show data in table form in this project? In my understanding, Repeater is most suitable since it faster than GridView. GridView is only suitable if you have edit function to go with your table.
This can be implemented using the OnDataBound event. The OnDataBound event of the GridView is executed after the GridView is populated with the records. Executed a loop in reverse over the GridView Rows and then the common Cells are identified and merged into single cell.
Below sample code merges the first & second columns (assuming that there are redundant values by comparing the above row(s)),
Feel free to leave a comment if you need more info.
protected void OnDataBound(object sender, EventArgs e)
{
for (int i = GridView1.Rows.Count - 1; i > 0; i--)
{
GridViewRow row = GridView1.Rows[i];
GridViewRow previousRow = GridView1.Rows[i - 1];
for (int j = 0; j < row.Cells.Count; j++)
{
if (row.Cells[j].Text == previousRow.Cells[j].Text)
{
if (previousRow.Cells[j].RowSpan == 0)
{
if (row.Cells[j].RowSpan == 0)
{
previousRow.Cells[j].RowSpan += 2;
}
else
{
previousRow.Cells[j].RowSpan = row.Cells[j].RowSpan + 1;
}
row.Cells[j].Visible = false;
}
}
}
}
}
In my asp.net application, I have used Gridview control, In which i have to add Dropdownlist at runtime for each cell.Which i am able to bind successfully.
Below is my code which inside row databound event,
foreach (GridViewRow row in gdvLocation.Rows) {
if (row.RowType == DataControlRowType.DataRow) {
for (int i = 1; i < row.Cells.Count; i++) {
var dlRouteType = new DropDownList();
dlRouteType.ID = "ddlRouteType";
dlRouteType.DataSource = GetRouteTypeList();
dlRouteType.DataTextField = "RouteType";
dlRouteType.DataValueField = "Id";
dlRouteType.DataBind();
row.Cells[i].Controls.Add(dlRouteType);
}
}
}
I have a button in my page, which has functionality to save data to database . While saving data i have to pass the value from Dropdownlist which i have added at runtime. On button click i am writing following code to get data from dropdownlist,
var ddlDropDown = (DropDownList)row.Cells[i].FindControl("ddlRouteType");
But i am getting null in ddlDropDown object. I have even added Update panel inside aspx page. Any suggessions most welcome.
Thanks in advance
Sangeetha
You have these errors in your code
RowDataBound already iterates through each rows and so all you need not write that foreach on top
You are iterating from index 1, index are zero-based. So start from zero.
The DropDownList ID must be unique, so better write something like,dlRouteType.ID = "ddlRouteType_" + i;
The code should be,
protected void gdvLocation_RowDataBound(object sender, GridViewRowEventArgs e)
{
//removed the foreach loop
var row = e.Row;
if (row.RowType == DataControlRowType.DataRow)
{
for (int i = 0; i < row.Cells.Count; i++) //changed index
{
var dlRouteType = new DropDownList();
dlRouteType.ID = "ddlRouteType_" + i; //gave unique id
dlRouteType.DataSource = GetRouteTypeList();
dlRouteType.DataTextField = "RouteType";
dlRouteType.DataValueField = "Id";
dlRouteType.DataBind();
row.Cells[i].Controls.Add(dlRouteType);
}
}
}
I have a loaded DataGrid. In that DataGrid the first column is a CheckBox, and the second column is "Name". Also I have saved one field "Name" in the database . Here I want to make the CheckBox to be checked if the Name is equal to the data which I stored in the database.
Here my problem is that ,I am getting only one CheckBox to to be checked.
ex:[ If my expected result is 1st, 2nd and 3dr CheckBoxes to be checked , But I am getting only the 3rd one as checked. ]
my sample code is
foreach (GridViewRow row in GrdProduct.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
Label lblproduct = (Label)row.FindControl("lblProduct");
CheckBox chkSelect = (CheckBox)row.FindControl("chkSelectAll");
for (int rowIndex = 0; rowIndex < dt.Rows.Count; rowIndex++)
{
DataRow r = dt.Rows[rowIndex];
if (Convert.ToString(r["productName"]) == lblproduct.Text)
{
chkSelect.Checked = true;
}
else
{
chkSelect.Checked = false;
}
}
}
Finally I got the solution ... Simply removed the else part
else
{
chkSelect.Checked = false; }
--
thank you all...
Sorry I am blind. You are looping through the datarows and of course you most likely have only one match. In all other cases it becomes unchecked right after. Use the following:
foreach (GridViewRow row in GrdProduct.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
Label lblproduct = (Label)row.FindControl("lblProduct");
CheckBox chkSelect = (CheckBox)row.FindControl("chkSelectAll");
chkSelect.Checked = false;
for (int rowIndex = 0; rowIndex < dt.Rows.Count || !chkSelect.Checked; rowIndex++)
{
DataRow r = dt.Rows[rowIndex];
if (Convert.ToString(r["productName"]) == lblproduct.Text)
{
chkSelect.Checked = true;
}
}
}
Als when comparing strings I recommend http://msdn.microsoft.com/en-us/library/system.string.equals(v=vs.110).aspx
COmpared what you are going to do with the data and controls in the grid I also recommend additional validation.