I want to program the checkboxes so that if a row is selected, the program will read the value in the first column of the gridview row and automatically check all rows that also have that value in their first column. I was able to do this using an array to store the value and running through each row, checking if this value was a match. If it matched, the checkbox was checked. This worked but was a very limited solution. When I tried to reverse the action, it simply rechecked that value automatically because that value was still in the array and I did not know how to distinguish between a check or un-check action. It was solely based on a change event.
int count = 0;
foreach (GridViewRow gvrow in GridView1.Rows)
{
CheckBox chk = (CheckBox)gvrow.FindControl("chkRow");
if (chk.Checked)
{
count++;
}
}
string [] dnum = new string[count];
int counter = 0;
foreach (GridViewRow row in GridView1.Rows)
{
CheckBox myCheckBox = row.FindControl("chkRow") as CheckBox;
if (myCheckBox.Checked)
{
if (counter > 0)
{
int number = counter - 1;
if (row.Cells[1].Text != dnum[number])
{
dnum[counter] = row.Cells[1].Text;
counter++;
}
}
else
{
dnum[counter] = row.Cells[1].Text;
counter++;
}
}
}
return dnum;
}
The array dnum should return the first column values for the checked rows . With this I can run through each row and check if any checkboxes need to be checked.
foreach (GridViewRow gvrow in GridView1.Rows)
{
CheckBox ChkBox = (CheckBox)gvrow.FindControl("chkRow");
if (ChkBox.Checked == true)
{
foreach (string s in first)
{
if (gvrow.Cells[1].Text == s)
{
ChkBox.Checked = true;
}
}
}
But now I am unable to figure out how to reverse the process, i.e when I uncheck one, all with the same first column value must uncheck, instead it just rechecks because that value is still in the array. I am open to completely different methods.
Many thanks,
Nicolas
I don't clearly understand your problem, Maybe you're looking for this?
use this code instead of your old one in check ChkBox loop.
if (gvrow.Cells[1].Text == s)
{
ChkBox.Checked = !ChkBox.Checked;
}
With ChkBox.Checked = !ChkBox.Checked, It'll reverse value in checkbox.
If it was true, It'll become false. If it was false, It'll become true.
Will just give another example, not sure on how you are implementing at your code so here it goes...
For example you have your gridview as below:
<asp:GridView ID="GridView1" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="CheckBox1"
OnCheckedChanged="CheckBox1_Click"
AutoPostBack="True" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And in your code behind..
mockData data below is just sample data for our gridview to demonstrate the check and un-check of same value based on selected checkbox property and column[1] value.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
var mockData = new[] {"1", "1", "2", "1", "3", "2"};
GridView1.DataSource = mockData;
GridView1.DataBind();
}
}
protected void CheckBox1_Click(object sender, EventArgs e)
{
var chkBox = (CheckBox) sender;
var selectedRow = chkBox.Parent.Parent;
var itemValue = ((GridViewRow)selectedRow).Cells[1].Text;
foreach (var chkItem in GridView1.Rows.Cast<GridViewRow>()
.Where(item => item.Cells[1].Text == itemValue)
.Select(item => item.Cells[0].FindControl("CheckBox1")).OfType<CheckBox>())
{
chkItem.Checked = chkBox.Checked;
}
}
}
If I click on checkbox in one row with value of "1", All rows with value of "1" should be automatically set to the property of selected checkbox.
Let me know if I misunderstood your requirement. You can apply to your code and let me know if it works :-) cheers.
Related
I have a GridView that uses the select. I want to grab the RegistrantId of which row is selected. I've tried a bunch of ways and haven't had luck.
C#
GridViewRow row = GridView1.SelectedRow;
if ((row != null))
{
string registrantId = GridView1.Rows[e.RowIndex].Cells[0].Value.ToString();
PnlEdit.Visible = true;
}
I need to figure out what to put at string registrantId =. It needs to equal the value of the RegistrantId from that row.
This attempt above, for example, gives me a compile error for RowIndex stating that "EventArgs does not contain a definition for RowIndex."
You can find the RowIndex like so:
string registrantId = GridView1.DataKeys[e.RowIndex]
This assumes that you have the DataKeyNames property set in your gridview
<asp:GridView runat="server" ID="GridView1" DataKeyNames="RegistrantId" >
Also, if this method is triggered by an event handler, you might want to change your null check condition to:
protected void GridView1_RowSelecting(object sender, GridViewSelectEventArgs e)
{
var registrantId = GridView1.DataKeys[e.RowIndex];
if(registrantId != null)
{
PnlEdit.Visible = true;
}
}
(You know the row exists because it was selected and that selection is what causes the event to trigger. The null check confirms you were able to obtain the registrantId from the row)
I'm populating a dataGridview in my winforms application using a list of strings (single unnamed column), however I need a way to select a single sell by it's value in order to change the text color.
How can I do this?
this is how I'm populating it:
List<String> companyNames = new List<String>();
//.. other logic that fills up companyNames
companyDataGridView.DataSource = this.companyNames.Select(x => new { Value = x }).ToList();
After which I need to somehow select the cell, based on the value it gets from the list.
You can use an eval in the html, this means that you can call the server side function in each row and determine its colour.
Luckily I have already used this recently and here is an example:
<asp:TemplateField HeaderText="Level Achieved">
<ItemTemplate>
<asp:Label ID="lblActual" runat="server" Text='<%# Bind("Actual") %>' BackColor='<%# GetLevelColour(Eval("Target"),Eval("Actual"))%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlAchievedLevel" runat="server">
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
Here you can see that the backcolour of the cell is determined by what is returned from the function GetLevelColour, I also pass in two parameters that are used in the function.
This may or may not be the sort of function you require, however my interpretation of the question was how to change colour of a cell when its value is equal to a predetermined value (in this case a word of length 2 as the length was output to the cell instead of the string).
I dont know much about Winforms, however I gave it a shot. Whilst I couldn't get the list to bind strings, I could pull the value out and compare against a known value. Is this the sort of thing you are looking for?
private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[0].Value.ToString() == "2")
{
//To colour the row
row.DefaultCellStyle.BackColor = Color.Red;
//To select the row
row.Selected = true;
}
}
}
This might not be pretty, but I ended up throwing this together.. and it seems to work.
private DataGridViewCell GetDataGridViewCellByValue(String value, DataGridView dataGridView)
{
List<DataGridViewCell> myCells = new List<DataGridViewCell>();
foreach (DataGridViewRow myRow in dataGridView.Rows)
{
foreach (DataGridViewCell myCell in myRow.Cells)
{
myCells.Add(myCell);
}
}
DataGridViewCell returnCell = myCells.FirstOrDefault(x => x.Value.ToString() == value);
if (returnCell != null)
{
return returnCell;
}
return null;
}
Then simply using this below I can get the desired cell:
DataGridViewCell testCell = this.GetDataGridViewCellByValue("Company1", this.companyDataGridView);
if (testCell != null)
{
testCell.Style.ForeColor = Color.Blue;
}
This could be a scalable and fast solution :
Dictionary<string, Color> valuesForColors = new Dictionary<string, Color>();
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.FormattedValue != null && valuesForColors.ContainsKey(e.FormattedValue.ToString()))
e.CellStyle.ForeColor = e.CellStyle.SelectionForeColor = valuesForColors[e.FormattedValue.ToString()];
}
I have an asp:Table that is populated with "products" using controls on the page (an 'add' button and a textbox for quantity).
In my code behind, whenever a table item is to be added, I first create an instance of Product, set its properties, and then add it to a list of products. I then do the following with the table:
- Clear its Rows collection
- Add the header row
- Bind the table to the list of Products
- Cache the list of Products, for later use
Each row in the Table begins with a cell containing a checkbox. Beneath the Table is a "Clear All" LinkButton. When the Clear All LinkButton is clicked,
I direct it to a method to cycle through all of the CheckBoxes, determine whether or not they are checked, and delete the corresponding entry in the Product list if checked == true.
So, in theory, when I re-bind the Products list to the Table, the Rows with that had their CheckBoxes selected should be removed.
This works if there is a single Row in the Table: when debugging, the CheckBox's checked property shows as "true", and the row is removed. However, if there is more than one row, the checked property for
all CheckBoxes appears as "false", and nothing is removed.
EDIT - It actually appears to remove the last row of the table, though the rest of the CheckBoxes are treated as not being checked.
Here is the table on the page:
<asp:Table ID="tblProducts" runat="server">
<asp:TableHeaderRow ID="tblProductsHead" runat="server" BorderStyle="Solid">
<asp:TableHeaderCell ID="colCheckBox" runat="server" Text="">
<asp:CheckBox ID="chkSelectAll" runat="server" Text="" />
</asp:TableHeaderCell>
<asp:TableHeaderCell ID="colProduct" runat="server" Text="Product"><asp:TableHeaderCell>
<asp:TableHeaderCell ID="colValue" runat="server" Text="Value"></asp:TableHeaderCell>
<asp:TableHeaderCell ID="colQuantity" runat="server" Text="Quantity"></asp:TableHeaderCell>
<asp:TableHeaderCell ID="colTotalValue" runat="server" Text="Total Value"></asp:TableHeaderCell>
</asp:TableHeaderRow>
</asp:Table>
<asp:LinkButton ID="lbtnClearAll" runat="server" Text="Clear All"
onclick="lbtnClearAll_Click"></asp:LinkButton>
...and here are the relevent sections of the code-behind:
private void ClearSelectedTableRows()
{
if (Cache["TableRows"] != null)
{
tableRows = Cache["TableRows"] as List<TableRow>;
Cache.Remove("TableRows");
TableRow row = new TableRow();
CheckBox rowBox = new CheckBox();
for (int i = 0; i < tableRows.Count; i++)
{
row = tblProducts.Rows[i+1]; // skip header row
rowBox = row.Cells[0].Controls[0] as CheckBox;
if (rowBox.Checked)
tableRows.RemoveAt(i);
}
TableRow headRow = tblProductsHead;
tblProducts.Rows.Clear();
tblProducts.Rows.Add(headRow);
Cache.Insert("TableRows", tableRows, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration);
PopulateTable();
}
}
private void PopulateTable()
{
if (Cache["TableRows"] != null)
{
List<TableRow> rows = Cache["TableRows"] as List<TableRow>;
foreach (TableRow row in rows)
tblProducts.Rows.Add(row);
}
}
I also think that your loop seems odd, and agree that you should also start with i=1.
A quick answer would be using --i right after removing a row
Someone left an answer, saying that the controls needed IDs for their properties to be properly assessed, but then deleted it. This turned out to be the root of the issue anyway. After giving the checkboxes IDs in the creation code, it began to work after a fashion.
However, further problems were then caused by using the RemoveAt() method; I was using the count of the "tableRows" list for the length of the loop, while at the same time potentially changing the length of that list inside the loop.
Its fixed now, and here's the updated method:
private void ClearSelectedTableRows()
{
if (Cache["TableRows"] != null)
{
tableRows = Cache["TableRows"] as List<TableRow>;
Cache.Remove("TableRows");
TableRow row = new TableRow();
CheckBox rowBox = new CheckBox();
List<TableRow> rowsToRemove = new List<TableRow>();
for (int i = 0; i < tableRows.Count; i++)
{
row = tblProducts.Rows[i+1]; // skip header row
rowBox = row.Cells[0].Controls[0] as CheckBox;
if (rowBox.Checked)
rowsToRemove.Add(tableRows[i]);
}
foreach (TableRow removeRow in rowsToRemove)
{
if (tableRows.Contains(removeRow))
tableRows.Remove(removeRow);
}
TableRow headRow = tblProductsHead;
tblProducts.Rows.Clear();
tblProducts.Rows.Add(headRow);
Cache.Insert("TableRows", tableRows, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration);
PopulateTable();
}
}
Thanks to those who helped, and thanks to the phantom answerer!
I have a repeater and on dataItembound i have something like this
((HtmlTableRow)e.Item.FindControl("prodName")).Visible = false;
This however sets all tablerows in the repeater to be invisible. I would like a specific one to be hidden. Is there a way to do this?
Heres the full imp
protected void RepeaterCategories_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
//Get category id
string catId = Request.QueryString["stctid"];
//Call function to check stock levels in the next loaded category
bool stock = checkCategoryStockLevels(catId);
if(stock == true)
{
((HtmlTableRow)e.Item.FindControl("catName")).Visible = false;
((HtmlTableRow)e.Item.FindControl("catImg")).Visible = false;
}
}
In the description you are retrieving the category identifier from the query string of the pages URL. This request will return the same value for all Repeater items and as such every "catName" and "catImg" HtmlTableRow will be hidden.
I assume you wish to hide the rows based on some value stored in the DataSource being bound to the repeater.
To do so you will need to access the DataItem in the ItemDataBound event and perform a check to determine which item requires the row to be hidden.
Below I have bound a List of strings to the Repeater, so I can access each item and perform a check like so, hiding only the HtmlTableRow in the ItemTemplate where the value of the DataItem equals "Item 1":
string dataItem = (string)e.Item.DataItem;
if (dataItem == "Item 1")
{
((HtmlTableRow)e.Item.FindControl("prodName")).Visible = false;
}
I assume you are binding something more complex such as a DataRow or some other Object. Either way the process is the same, cast the DataItem and perform your check.
I would look into using a ListView or a DataList instead, because then you can use data keys to determine row visibility based on a certain value.
I got it.
for (int repeaterCount = 0; count < repeaterID.Items.Count; count++)
{
Label label = (Label)repeaterID.Items[repeaterCount].FindControl("labelID");
label.Text = "Text";
}
Thanks to all that helped
How can I programmatically uncheck all rows in a DataGridViewCheckboxColumn in a datagridview?
I can get the correct value of the checkbox using
(bool)row.Cells[CheckBoxColumn.Index].FormattedValue
but that's only a getter.
I have tried setting the value of the cell using
(bool)row.Cells[CheckBoxColumn.Index].value = false
but that doesn't affect the FormattedValue.
How can I solve this?
You do sth. like:
(row.Cells[CheckBoxColumn.Index] as DataGridViewCheckBoxCell).value = false;
You just forgot to cast to the correct type, a generic DataGridViewCell doesn't know its value-type.
Have you tried casting the first control in the checkbox column to checkbox and then setting 'Checked' to true?
Try something to this extent.
((DataGridViewCheckBoxCell)e.Rows[0].Cells[0]).Selected = true
you should just use YourDataGridview.EndEdit() after checking.
(row.Cells[CheckBoxColumn.Index] as DataGridViewCheckBoxCell).value = false;
YourDataGridview.EndEdit();
Haven't checked but you can try;
CheckBox cb = (row.Cells[CheckBoxColumn.Index].Controls[0] as CheckBox);
if(cb != null)
{
cb.Checked = false;
}
It's type may be different. Just debug and cast it to what it is.
foreach (DataGridViewRow dr in dataGridView1.Rows)
{
dr.Cells[0].Value = true;//sıfırın
}
If you use dataGridView1_ContextClick just for do "false" datagidviewCheckBox Column need this Code :
dataGridView1.CancelEdit();
but if you need all rows of CheckBoxColumns of DataGrid :
private void button1_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow r in dataGridView1.Rows)
{
r.Cells["statusBox"].Value = true;
}
}
Depending on what you wish to do
If it is about the selected row, then you can:
DataGridViewRow row = dataGridViewName.CurrentRow;
//This will assign the opposite value of the Cell Content
row.Cells["ColumnName"].Value = !Convert.ToBoolean(row.Cells["ColumnName"].Value);
However if you wish to do it for the whole DataGridView table then:
foreach (DataGridViewRow row in dataGridViewName.Rows)
{
//This will assign the opposite value of the Cell Content
row.Cells["ColumnName"].Value = !Convert.ToBoolean(row.Cells["ColumnName"].Value);
}
Whatever suites you. Keep it up!
Loop through each row of grid view and use the find control method:
foreach ( GridViewRow row in myGridView )
{
CheckBox checkBox = ( CheckBox ) row.FindControl( "myCheckBox" );
checkbox.Checked = false;
}
foreach (DataGridViewRow row in datagridviewname.Rows)
{
row.Cells[CheckBoxColumn1_Name].Value = false;
}