I try to multiselect values in listbox into template field, when it is in edit mode. Is there a way to do it?
I tried something like this. I add HiddenField to bind there a values and then w JS code I want to select selected values (I can do it but I dont have a class in HiddenField so it isn't a good solution).
Also I don't know is there a chance to do it by server side becasue it didn't recognize Id's of mine Listbox
<asp:TemplateField HeaderText="Conditions" ItemStyle-Width="100px">
<EditItemTemplate>
<asp:HiddenField runat="server" ID="hdn_dd_conditions" class="bottom" Value='<%# Bind("conditions") %>' />
<asp:ListBox ID="dd_conditions" runat="server" CssClass="conditions" SelectionMode="Multiple" multiple="multiple">
<asp:ListItem Value="Value1" Text="Text2"></asp:ListItem>
<asp:ListItem Value="Value2" Text="Text2"></asp:ListItem>
<asp:ListItem Value="Others" Text="Others"></asp:ListItem>
</asp:ListBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("conditions") %>' Font-Size="10px"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Any ideas?
You need to access the ListBox in the RowDataBound event of the GridView
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//check if the row is a datarow and in edit mode
if (e.Row.RowType == DataControlRowType.DataRow && (e.Row.RowState & DataControlRowState.Edit) > 0)
{
//cast the row back to a datarowview
DataRowView row = e.Row.DataItem as DataRowView;
//use findcontrol to locate the listbox and cast it
ListBox lb = e.Row.FindControl("dd_conditions") as ListBox;
//loop all the items in a listbox
for (int i = 0; i < lb.Items.Count; i++)
{
//check the values and set the Selected property
if (lb.Items[i].Value == row["conditions"].ToString())
{
lb.Items[i].Selected = true;
}
}
}
}
I a newbie to asp.net. I have created a DB table in sqlserver with 3 columns; ImageID, Filename & Score.
FileName is C:\pics\beads.png or C:\pics\moreimages\scenary.jpeg.
Using C# asp.net, I have created a GridView. This Gridview should populate
(column 1)ImageID and get the image from the Filename (column2) and I have 2 Checkboxlist created as shown below which should accept score for the images from user and save it into the DB table.
Question 1 .
I am able to populate Image ID, but Images are not getting populated.
Question 2.
I do not know how to access the checkboxlist since it is in template. The checked is in the default select and doesn't change even if I click on it. Which method/property should be used to do save the selection to the database. Here's my code
<form id="form1" runat="server">
<p style="height: 391px">
<asp:GridView ID="GridView1" runat="server" Caption="Logos" Height="299px" Width="577px" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="ImageID" HeaderText="ImageID" />
<asp:ImageField DataImageUrlField="FileName" ControlStyle-Width="100"
ControlStyle-Height="100" HeaderText="Image" AlternateText="No image">
<ControlStyle Height="100px" Width="100px"></ControlStyle>
</asp:ImageField>
<asp:TemplateField HeaderText="Score" AccessibleHeaderText="CheckBoxList" ValidateRequestMode="Enabled">
<ItemTemplate>
<asp:CheckBoxList runat="server" AutoPostBack="true" RepeatColumns="3" ID="test">
<asp:ListItem Selected="True" Value="5">Good</asp:ListItem>
<asp:ListItem Value="0">Not Good </asp:ListItem>
<asp:ListItem Value="3">OK</asp:ListItem>
</asp:CheckBoxList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Save" Width="130px" />
<asp:Button ID="Button2" runat="server" OnClientClick="javaScript:window.close(); return false;" Text="Exit" Width="102px" />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</p>
</form>
public string sqlSel = #"SELECT TOP 3 [ImageID],FileName FROM [db1].[ImagesTest] where [Score] is null";
protected void Page_Load(object sender, EventArgs e)
{
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString))
{
connection.Open();
SqlCommand cmdSel = new SqlCommand(sqlSel, connection);
SqlDataReader reader1 = cmdSel.ExecuteReader();
while (reader1.Read())
{
DataSet ds = GetData(sqlSel);
if (ds.Tables.Count > 0)
{
GridView1.DataSource = ds;
GridView1.DataBind();
}
else
{
Response.Write("Unable to connect to the database.");
}
}
}
}
private DataSet GetData(string cmdSel)
{
String strConnString = System.Configuration.ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString;
DataSet ds = new DataSet();
try
{
SqlConnection con = new SqlConnection(strConnString);
SqlDataAdapter sda = new SqlDataAdapter(cmdSel,con);
sda.Fill(ds);
}
catch (Exception ex)
{
Response.Write("IN EXCEPTION "+ex.Message);
return null;
}
return ds;
}
Thanks for ur time
Rashmi
There are several issues with your code, here is what it should be fixed:
How to fix the images (Question 1)
As #Guilherme said in the comments, for images use URLs instead of disk paths.
Replace the images disk paths C:\pics\beads.png or C:\pics\moreimages\scenary.jpeg to something like Images/beads.png and Images/scenary.jpeg.
For this to work, you will need to have a folder named Images that contains these two files on the same directory level as your .aspx file.
Adjust your GridView1 declaration in the ASPX file
On your GridView1 declaration you should:
attach a handler to the OnRowDataBound event. This will allow you to properly bind the Score dataset column to the Score gridview column
set the DataKeyNames property on the grid to what should be the primary key for your images table (in this case DataKeyNames="ImageID")
use a RadioButtonList instead of a CheckboxList, because according to your dataset you can only set one value, which is what the RadioButtonList does. The CheckboxList is normally used when multiple selection is needed.
attach a handler to the SelectedIndexChanged event on the RadioButtonList. This will allow you to save the new values to the database (Question 2)
Here's how your GridView declaration should look like:
<asp:GridView ID="GridView1" runat="server" Caption="Logos" Height="299px" Width="577px" AutoGenerateColumns="False" OnRowDataBound="GridView1_RowDataBound" DataKeyNames="ImageID">
<Columns>
<asp:BoundField DataField="ImageID" HeaderText="ImageID" />
<asp:ImageField DataImageUrlField="FileName" ControlStyle-Width="100"
ControlStyle-Height="100" HeaderText="Image" AlternateText="No image">
<ControlStyle Height="100px" Width="100px"></ControlStyle>
</asp:ImageField>
<asp:TemplateField HeaderText="Score" AccessibleHeaderText="RadioButtonList" ValidateRequestMode="Enabled">
<ItemTemplate>
<asp:RadioButtonList runat="server" AutoPostBack="true" RepeatColumns="3" ID="test" OnSelectedIndexChanged="test_SelectedIndexChanged">
<asp:ListItem Value="5">Good</asp:ListItem>
<asp:ListItem Value="0">Not Good </asp:ListItem>
<asp:ListItem Value="3">OK</asp:ListItem>
</asp:RadioButtonList>
<!-- UPDATED! - keep the old values in a hidden field -->
<asp:HiddenField runat="server" ID="hfOldScore" Value='<%# Eval("Score") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Adjust your code behind value in your .ASPX.CS file (Question 2)
On the code behind, you will also need to:
Make sure you are binding to the GridView only once in the Page_Load event, by checking the IsPostBack property
(Optional, but recommended) Move the logic of getting data (with the SQLConnection code) in a separate method that will handle only data retrieval
Implement the handler for the OnRowDataBound event. This will bind any values from the Score column to the RadioButtonList control
Implement the handler for the SelectedIndexChecked event of the RadioButtonList control. This will allow you to save to the database the new values
Finally, here's the entire code-behind code:
protected void Page_Load(object sender, EventArgs e)
{
//bind only the first time the page loads
if (!IsPostBack)
{
DataSet ds = GetData(sqlSel);
if (ds.Tables.Count > 0)
{
GridView1.DataSource = ds;
GridView1.DataBind();
}
else
{
Response.Write("Unable to connect to the database.");
}
}
}
private DataSet GetData(string cmdSel)
{
//normally you should query the data from the DB
//I've manually constructed a DataSet for simplification purposes
DataSet ds = new DataSet();
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("ImageID", typeof(int)));
dt.Columns.Add(new DataColumn("FileName", typeof(string)));
dt.Columns.Add(new DataColumn("Score", typeof(int)));
dt.Rows.Add(100, #"Images/beads.png", 0);
dt.Rows.Add(200, #"Images/moreimages/scenary.jpeg", 3);
dt.Rows.Add(300, #"Images/moreimages/scenary.jpeg", 5);
ds.Tables.Add(dt);
return ds;
}
protected void Button1_Click(object sender, EventArgs e)
{
//UPDATED - iterate through all the data rows and build a dictionary of items
//to be saved
Dictionary<int, int> dataToUpdate = new Dictionary<int, int>();
foreach (GridViewRow row in GridView1.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
int imageID = (int)GridView1.DataKeys[row.RowIndex].Value;
int oldScore;
int newScore;
int.TryParse((row.FindControl("hfOldScore") as HiddenField).Value, out oldScore);
int.TryParse((row.FindControl("test") as RadioButtonList).SelectedValue, out newScore);
if (oldScore != newScore)
{
dataToUpdate.Add(imageID, newScore);
}
}
}
//update only the images that were changed
foreach (var keyValuePair in dataToUpdate)
{
SaveToDB(keyValuePair.Key, keyValuePair.Value);
}
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//we are only interested in the data Rows
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRow dataRow = (e.Row.DataItem as DataRowView).Row;
//manually bind the Score column to the RadioButtonlist
int? scoreId = dataRow["Score"] == DBNull.Value ? (int?)null : (int)dataRow["Score"];
if (scoreId.HasValue)
{
RadioButtonList test = e.Row.FindControl("test") as RadioButtonList;
test.ClearSelection();
test.SelectedValue = scoreId.Value.ToString();
}
}
}
protected void test_SelectedIndexChanged(object sender, EventArgs e)
{
RadioButtonList test = sender as RadioButtonList;
GridViewRow gridRow = test.NamingContainer as GridViewRow;
//obtain the current image Id
int imageId = (int)GridView1.DataKeys[gridRow.RowIndex].Value;
//obtain the current selection (we will take the first selected checkbox
int selectedValue = int.Parse(test.SelectedValue);
//UPDATED! - saves are now handled on the Save button click
//SaveToDB(imageId, selectedValue);
}
private void SaveToDB(int imageId, int score)
{
//UPDATED!
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString))
{
connection.Open();
using (SqlCommand command = connection.CreateCommand())
{
command.Parameters.Add("#ImageID", imageId);
command.Parameters.Add("#Score", score);
command.CommandText = #"update [db1].[ImagesTest] set Score = #Score where [ImageID] = #ImageID";
command.ExecuteNonQuery();
}
}
}
UPDATED!
The declaration of the GridView1 now contains a hidden field containing the Score value. You can use this hidden field to determine which row has changed, so you can trigger a save only on the changed ones
Save is now done on the click of the Save button, by iterating through the rows of the grid an building a Dictionary<int,string> to keep only the changes.
SaveToDB method should work, but I cannot test this myself.
Question 2:
To access your checkbox you can use.
GridViewRow row = GridView1.Rows[i];
CheckBox Ckbox = (CheckBox)row.FindControl("test");
For Question 1
Instead of ImageField you can use use ASP:Image in Templatefield like this
<asp:TemplateField HeaderText="Score" AccessibleHeaderText="CheckBoxList" ValidateRequestMode="Enabled">
<ItemTemplate>
<asp:Image ID="imageControl" runat="server" ImageUrl='<%# Eval("Filename") %>'></asp:Image>
</ItemTemplate>
</asp:TemplateField>
For Question 2
This is one of the example for how to access each Checkbox list inside gridview
For Each gvr As GridViewRow In Gridview1.Rows
If (CType(gvr.FindControl("CheckBox1"), CheckBox)).Checked = True Then
ReDim uPrimaryid(iCount)
uPrimaryid(iCount) = New Integer
uPrimaryid(iCount) = gvr.Cells("uPrimaryID").Text
iCount += 1
End If
Next
How would you get the control type of an EditTemplate control in a gridview in ASP.NET?
To get a bound control's type I simply do this
foreach (TableCell cell in grdViewDetails.Rows[e.RowIndex].Cells)
{
//set the employeeid so you can update the dataset
if (cell.Controls[0] is CheckBox)
{
CheckBox check = (CheckBox)cell.Controls[0];
//Do stuff with the control and the text inside the control etc;
}
}
but I cant seem to find the controls in the templates. They just skip this if.
What I've tried to no avail.
foreach (TableCell cell in grdViewDetails.Rows[e.RowIndex].Cells)
{
var test1 = cell.Controls[0];
columnName = dsOriginal.Tables[0].Columns[startOfColumns].ColumnName; //[System.Web.UI.LiteralControl] I can find the Column Name but it't not a normal control... It's a LiteralControl?
var test2 = cell.FindControl("CheckWeek2"); //[System.Web.UI.WebControls.Calendar] = {SelectedDate = The name 'SelectedData' does not exist in the current context}
}
My Gridview control Template
<asp:TemplateField HeaderText="week2" SortExpression="week2">
<EditItemTemplate>
<asp:CheckBox ID="CheckWeek2" runat="server" Checked='<%# Bind("week2") %>'></asp:CheckBox>
</EditItemTemplate>
<ItemTemplate>
<asp:CheckBox ID="Label2" runat="server" Enabled="false" Checked='<%# Bind("week2") %>'></asp:CheckBox>
</ItemTemplate>
</asp:TemplateField>
try below,
if (this.grdViewDetails.EditIndex != -1)
{
CheckBox b = grdViewDetails.Rows[grdViewDetails.EditIndex].FindControl("CheckWeek2") as CheckBox;
if (b != null)
{
//do something
}
}
Try this:
if (e.Row.RowType == DataControlRowType.DataRow)
{
CheckBox CheckWeek2 = (CheckBox)e.Row.FindControl("CheckWeek2");
}
I have an item template in a GridView and I want to create a dropdown for each row and bind it to a value retrieved from the database.. but I am not sure how to do this.. this is what i have so far.. but not sure where to put the code to populate the drop down per row..
<ItemTemplate>
<asp:DropDownList runat="server" ID="ddlMyQuantity" SelectedValue='<%#
(DataBinder.Eval(Container.DataItem,"Quantity")) %>'>
</asp:DropDownList>
</ItemTemplate>
and in code behind, not sure how to or where to put this so that it is created on every row..
public void BindMyQuantity()
{
for (int i = 1; i < 15; i++)
{
ddlMyQuantity.Items.Add(i.ToString());
}
}
Also i am not sure if i can do that, but the code is not complaining.. adding SelectedValue in the asp declaration
You can use OnRowDataBound to dynamically bind your dropdown:
protected void GridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
var dropdownList = (DropDownList)e.Row.FindControl("ddlMyQuantity");
for (int i = 1; i < 15; i++)
{
dropdownList.Items.Add(i.ToString());
}
dropdownList.SelectedValue =
Convert.ToString(DataBinder.Eval(e.Row.DataItem, "Quantity"));
}
}
Add binding:
<asp:GridView ... OnRowDataBound="GridView_RowDataBound">
...
</asp:GridView>
As per my knowledge, the best option would be to write this code in "RowDataBound" event of the Grid. See sample code below.
protected void GridView_RowDataBound(..)
{
if (e.Row.RowType.Equals(DataControlRowType.DataRow))
{
DropDownList ddl = e.Row.FindControl("ddlMyQuantity") as DropDownList;
if (ddl != null)
{
for (int i = 1; i < 15; i++)
{
ddl.Items.Add(i.ToString());
}
}
}
}
In the aspx page, provide this
<ItemTemplate>
<asp:DropDownList runat="server" ID="ddlMyQuantity"></asp:DropDownList>
</ItemTemplate>
Hope this Helps!!
<asp:TemplateField HeaderText="Type Cargo" HeaderStyle-HorizontalAlign="Center" ItemStyle-Width="10%" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" DataValueField="DESCRIPTION"></asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
Code Behind will look like this...
Dim rowId As DropDownList
For i As Integer = 0 To gridView1.Rows.Count - 1
Dim gridrow As GridViewRow = gridView1.Rows(i)
rowId = DirectCast(gridrow.FindControl("DropDownList1"), DropDownList)
Dim dt As DataTable = Get_List()
rowId.DataSource = dt
rowId.DataBind()
Next
Get_List is a Function that returns a DataTable
3 Dropdownlists in same row when I edit.
When 1 dropdownlist has a selection, the other 2 should go to index of 0 (the empty one).
Example of my code:
<asp:TemplateField HeaderText="Project" SortExpression="Project">
<ItemTemplate>
<%#Eval("Project") %>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ProjectDropDownList" runat="server" AutoPostBack="true" OnSelectedIndexChanged="ProjectDropDownList_Changed" AppendDataBoundItems="true"
DataSourceID="ProjectDataSource" DataTextField="navn" DataValueField="navn">
<asp:ListItem>-- choose one --</asp:ListItem>
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
My SelectionChanged even handler:
protected void ProjektDropDownList_SelectionChanged(object sender, EventArgs e)
{
DropDownList project = (DropDownList) GridView1.Rows[GridView1.SelectedIndex].FindControl("ProjectDropDownList");
DropDownList kunde = (DropDownList)GridView1.Rows[GridView1.SelectedIndex].FindControl("KundeDropDownList");
DropDownList øvrige = (DropDownList)GridView1.Rows[GridView1.SelectedIndex].FindControl("ØvrigeDropDownList");
if(project.SelectedIndex >= 0 && kunde != null && øvrige != null) {
kunde.SelectedIndex = 0;
øvrige.SelectedIndex = 0;
}
}
I get a nullpointer when trying to fetch other controls in the same row... How do I fix this?
I'm not sure it's the SelectedIndex that you're looking for. Isn't there an EditItemIndex which you should be using?