I use datatable as data source for grid view.
And one of the columns of the data table have to display image.
Here is how I create data table:
DataTable dt = new DataTable();
List<ReportFeature> featureProps = fim.getFeatureProperties().ToList();
var headers = featureProps.FirstOrDefault().Properties.Select(k => k.Key).ToList();
headers.ForEach((h) => dt.Columns.Add(h, typeof(string)));
foreach (var feat in featureProps)
{
DataRow row = dt.NewRow();
foreach (var header in headers)
{
row[header] = feat.Properties[header];
}
dt.Rows.Add(row);
}
And here is how I bind the data table to grid view datas source:
gvfeatureProps.DataSource = dt;
gvfeatureProps.DataBind();
one of the columns in data table contains path to image.
My question is how do I make images displayed in my grid view after bind programatically?
All within <Columns> you can also use template fields
Using a asp.net Image:
<asp:TemplateField>
<ItemTemplate>
<asp:Image ID="Image1" runat="server" ImageUrl='<%# Eval("MyImageUrlColumnName") %>' />
</ItemTemplate>
</asp:TemplateField>
or the standard HTML img:
<asp:TemplateField>
<ItemTemplate>
<img src='<%# Eval("MyImageUrlColumnName") %>' />
</ItemTemplate>
</asp:TemplateField>
If you need a bit more flexibility that the ImageField used in previous answer.
If you want to add an image programatically, use the RowDataBound event.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//check if the row is a datarow
if (e.Row.RowType == DataControlRowType.DataRow)
{
//cast the row back to a datarowview
DataRowView row = e.Row.DataItem as DataRowView;
//create a new cell
TableCell cell = new TableCell();
//create an image
Image img = new Image();
img.ImageUrl = row["imageUrl"].ToString();
//add the image to the cell
cell.Controls.Add(img);
//add the cell to the gridview
e.Row.Controls.Add(cell);
//or use addat if you want to insert the cell at a certain index
e.Row.Controls.AddAt(0, cell);
//or don't add a new cell but add it to an existing one (replaces original content)
e.Row.Cells[2].Controls.Add(img);
}
}
Related
I am building a web application to construct a document. The document has paragraphs (outer repeater) and subparagraphs (inner repeater). What I'm looking for is a way to add a blank subparagraph to an existing document.
My markup:
<asp:Repeater ID="ParagraphRepeater" runat="server"
OnItemDataBound="ParagraphRepeater_ItemDataBound" >
<ItemTemplate>
<asp:TextBox ID="ParagraphTitleTextBox" runat="server" Font-Bold="true" Width="300px"
Text='<%# Eval("ParagraphTitle") %>'></asp:TextBox>
<br />
<asp:TextBox ID="ParagraphTextTextBox" runat="server" TextMode="MultiLine" Wrap="true"
width="1100px" Height="50px" Text='<%# Eval("ParagraphText") %>'></asp:TextBox>
<asp:Button ID="DeleteParagraphButton" runat="server" Text="Delete" OnClick="DeleteParagraphButton_Click" />
<asp:Repeater ID="SubParagraphRepeater" runat="server" DataSourceID="SubParagraphSqlDataSource">
<ItemTemplate>
<div style="margin-left: 30px">
<asp:TextBox ID="SubParagraphTitleTextBox" runat="server" Font-Underline="true" Width="200px"
Text='<%# Eval("SubParagraphTitle") %>'></asp:TextBox>
<br />
<asp:TextBox ID="SubParagraphTextTextBox" runat="server" TextMode="MultiLine" Wrap="true"
Width="1050px" Height="50px" Text='<%# Eval("SubParagraphText") %>'></asp:TextBox>
<asp:Button ID="DeleteSubParagraphButton" runat="server" Text="Delete"
OnClick="DeleteSubParagraphButton_Click" />
<br />
</div>
</ItemTemplate>
</asp:Repeater>
<br />
<br />
<br />
</ItemTemplate>
My code:
protected void MultiView1_ActiveViewChanged(object sender, EventArgs e)
{
if (MultiView1.GetActiveView() == InputView)
{
BuildParagraphDataTable();
BuildSubParagraphDataTable();
if (RevisionsDropDownList.SelectedValue == "0")
{
// User is creating a new document
// Call method to create a datatable for the form row
SetFormRow();
// Call method to create a datatable for the paragraph row
AddParagraph();
DataTable dt = (DataTable)ViewState["ParagraphTable"];
ParagraphRepeater.DataSource = dt;
ParagraphRepeater.DataBind();
}
else
{
// User is opening an existing document
// Get the formId and save it to ViewState
int formId = Convert.ToInt32(RevisionsDropDownList.SelectedValue);
ViewState["FormId"] = formId.ToString();
// Bind the Paragraph repeater to its sqlDataSource
ParagraphRepeater.DataSource = ParagraphSqlDataSource;
ParagraphRepeater.DataBind();
}
}
}
protected void AddParagraph()
{
int paragraphId;
DataTable dt = (DataTable)ViewState["ParagraphTable"];
DataRow dr = dt.NewRow();
if (ViewState["ParagraphId"] != null)
paragraphId = Convert.ToInt32(ViewState["ParagraphId"]);
else
paragraphId = 0;
paragraphId--;
int formId = Convert.ToInt32(ViewState["FormId"]);
dr["ParagraphId"] = paragraphId;
dr["FormId"] = formId;
dr["ParagraphTitle"] = string.Empty;
dr["ParagraphText"] = string.Empty;
dr["CreatorId"] = string.Empty;
dr["RevisorId"] = string.Empty;
dt.Rows.Add(dr);
ViewState["ParagraphTable"] = dt;
ViewState["ParagraphId"] = paragraphId;
}
protected void AddSubParagraph()
{
DataTable dt = (DataTable)ViewState["SubParagraphTable"];
DataRow dr = dt.NewRow();
int paragraphId = Convert.ToInt32(ViewState["ParagraphId"]);
dr["ParagraphId"] = paragraphId;
dr["SubParagraphTitle"] = string.Empty;
dr["SubParagraphText"] = string.Empty;
dr["CreatorId"] = string.Empty;
dr["RevisorId"] = string.Empty;
dt.Rows.Add(dr);
ViewState["SubParagraphTable"] = dt;
}
protected void ParagraphRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
AddParagraph();
DataTable parentDataTable = (DataTable)ViewState["ParagraphTable"];
DataRow lastDTRow = parentDataTable.Rows[parentDataTable.Rows.Count - 1];
int paragraphId = (int)ViewState["ParagraphId"];
DataRowView thisParagraphRowView = (DataRowView)e.Item.DataItem;
paragraphId = (int)thisParagraphRowView.Row["ParagraphId"];
lastDTRow["ParagraphId"] = thisParagraphRowView.Row["ParagraphId"];
lastDTRow["FormId"] = thisParagraphRowView.Row["FormId"];
lastDTRow["ParagraphTitle"] = thisParagraphRowView.Row["ParagraphTitle"];
lastDTRow["ParagraphText"] = thisParagraphRowView.Row["ParagraphText"];
ViewState["ParagraphTable"] = parentDataTable;
ViewState["ParagraphId"] = paragraphId.ToString();
DataTable childDataTable;
DataRowView thisSubParagraphRowView;
Repeater childRepeater = (Repeater)e.Item.FindControl("SubParagraphRepeater");
foreach (RepeaterItem item in childRepeater.Items)
{
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
thisSubParagraphRowView = (DataRowView)item.DataItem;
if (thisSubParagraphRowView != null)
{
AddSubParagraph();
childDataTable = (DataTable)ViewState["SubParagraphTable"];
lastDTRow = childDataTable.Rows[childDataTable.Rows.Count - 1];
lastDTRow["ParagraphId"] = thisSubParagraphRowView.Row["ParagraphId"];
lastDTRow["SubParagraphTitle"] = thisSubParagraphRowView.Row["SubParagraphTitle"];
lastDTRow["SubParagraphText"] = thisSubParagraphRowView.Row["SubParagraphText"];
ViewState["SubParagraphTable"] = childDataTable;
}
}
}
}
}
When the user opens an existing form, the itemDataBound code populates the datatables for the paragraphs and subparagraphs. (These datatables will be used in the update to the database.)
When the user creates a new form, the setForm() and addParagraph() methods are called to create the form ID and add a blank paragraph. No blank subparagraph is added - the user must click a button to do so.
As for the data model, there is one Form (the user selects it from a ddl). A Form can have 1 to many paragraphs, and paragraphs can have zero to many subparagraphs.
I need to create a blank row in the inner repeater for a particular row in the outer repeater (the paragraph that the cursor is currently located in, or if the cursor is located in a subparagraph, the parent paragraph). How do I do that? I've done a ton of digging on Google but cannot find an entry that addresses this issue. Thanks.
The answer is to move the "AddSubParagraph" button from a standalone position to be inside the outer repeater. That way, the repeater can be located by using the "NamingContainer" attribute of the button. Then it's a matter of finding the inner repeater Repeater innerRepeater = (Repeater)outerRepeater.FindControl("childRepeater");, and adding a row to it. I can add the row but I'm having trouble DataBinding the inner repeater.
What I do is keep datatables in viewstate for each repeater, and mirror the data between the repeaters and the datatables. When I need to add a row, I add it to the datatable and then databind the repeater to the datatable. But I get an error: The line it errors on is childRepeater.Datasource = dt;. The error is "DataSource and DataSourceId are both defined. Remove one definition." DataSourceId is defined on the childRepeater in the markup, pointing to a SQLDataSource. So I need to find a way to bind the inner repeater to its SQLDataSource at retrieval time, on the fly.
One snag: I'm thinking I'd use the ItemDataBound event to do the databinding. But I already have a lot of code there (see above). Is there another event I can use that makes sense?
I ask this question because I think I have different problem with this : How to hide gridview column after databind?
My gridview has data from database. I don't set any "td" in my code, but html changes the gridview to table and have "td". The problem is, I don't want the cell or "td" is shown on the page, I just want to receive the data in the cell to show the image in the database.
This is code to retrieve data from database:
public static DataTable FetchAllImagesInfo(int id)
{
string sb = "Select img_content, Img_id, csrid FROM images WHERE Img_Id = " + id + ";";
SqlConnection conn = DatabaseFactory.GetConnection();
SqlDataAdapter da = new SqlDataAdapter(sb, conn);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
This is codebehind to bind GridView, here I tried to set Visible to true or false, but it doesn't work. I set column index manually because it's only has 3 column :
GridView1.DataSource = ProductAllLocationCatalog.FetchAllImagesInfo(_id);
GridView1.DataBind();
GridView1.Columns[0].Visible = true;
GridView1.Columns[1].Visible = false;
GridView1.Columns[2].Visible = false;
And, this is my aspx code :
<asp:GridView ID="GridView1" runat="server">
<Columns>
<asp:TemplateField runat="server">
<ItemTemplate runat="server">
<asp:Image ID="image1" runat="server" ImageUrl='<%#"Handler.ashx?csrid="+Eval("csrid") %>' style="max-height:400px; max-width:940px; text-align:center; margin:auto; display:block;" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I just need the image from the database, not other. But if I only SELECT the image, gridview can not do DataBind(), and I can't get value of "csrid".
Thank you!
Try
protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
e.Row.Cells[1].Visible = false;
e.Row.Cells[2].Visible = false;
}
I believe the issue is that your GridView is automatically generating your columns, and the GridView.Columns property only stores explicitly declared columns. Instead of hiding the column, you can hide the cells comprising the columns you don't want when each row is bound. It seems like there should be a better way to handle this, but outside of using explicitly declared columns, I don't know one.
I have Gridview with 10 Rows each row have 2 columns which is Textbox and Checkbox.
what i have to do is have to enter textbox Value as 1000 and i Clicked the Checkbox at first Row then value must go to Textbox of Second row and i clicked checkbox of Second Row then value must be go to third row of Textbox and so on.
i tried this,
protected void txtintroId_TextChanged(object sender, EventArgs e)
{
TextBox txt = (TextBox)sender;
GridViewRow grid = ((GridViewRow)txt.Parent.Parent.Parent);
TextBox txtIntro = (TextBox)txt.FindControl("txtintroId");
}
here i get the 1st row Value but How do i pass this to second Row.
Assist me
Here is full working code(as per your requirement )
Create a gridview like this
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%#Eval("txtcolumn") %>'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server" AutoPostBack="True" OnCheckedChanged="CheckBox2_CheckedChanged" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Add a function in code behind C#
protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
{
int rowNo=0;
foreach (GridViewRow GV1 in GridView1.Rows)
{
rowNo++;//
if (rowNo < GridView1.Rows.Count) //Checking that is this last row or not
{
//if no
CheckBox chkbx= (CheckBox)GV1.FindControl("CheckBox1");
TextBox curenttxtbx = (TextBox)GV1.FindControl("TextBox1");
if (chkbx.Checked == true )
`{
int nextIndex = GV1.RowIndex + 1;//Next row
TextBox txtbx = (TextBox)GridView1.Rows[nextIndex].FindControl("TextBox1");
txtbx.Text = curenttxtbx.Text;
}
}
//if yes
else
{
//For last row
//There is no next row
}
}
}
And i used this data table as data source
DataTable table = new DataTable();
table.Columns.Add("txtcolumn", typeof(string));
table.Rows.Add("1");
table.Rows.Add("32");
table.Rows.Add("32");
table.Rows.Add("32");
table.Rows.Add("3");
table.Rows.Add("32");
table.Rows.Add("32");
I tested this code it is working as per your requirement. (And SORRY for this bad formatting. i will do it later or please some body correct the formating :))
I am working on an ASP.net application ( c#) . In it I have a grid view with columns displayed as ItemTemplates. I want to edit the values of one column.
I have an update button below the grid view. So when I click on update, the new values should be updated to the database.
I am using a list collection to bind the data to grid view.
I have no idea how to accomplish this.
Lets say you have TextBox inside the column, where the user is going to update new values. You can iterate through the gridview rows, in this manner
foreach(GridViewRow row in GridView1.Rows) {
if(row.RowType == DataControlRowType.DataRow) {
TextBox txtbx= row.FindControl("txtbx") as TextBox;
//using the txtbx you can get the new values and update then to the db
}
}
foreach(GridViewRow row in GridView1.Rows)
{
if(row.RowType == DataControlRowType.DataRow)
{
String str = ((txtbx)(row.Cells[2].Controls[0])).Text;
}
}
Check your cell value for textbox.
If you are using a GridView, are you also using a backing object (some sort of collection) to bind to the grid rows - it seems likely since you are using ItemTemplates to display them.
In this case, can you access the items you wish to change from this backing collection?
EDIT
Comment says that you're using a list to bind the grid, so why not make your changes to the list items and send those back to the database?
foreach(var listItem in MyList)
{
listItem.ThingToChange = newValueForThisProperty;
}
SubmitChangesToDatabase(MyList);
I created a full working demo and tested it:
GridBulkEdit.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeFile="GridBulkEdit.aspx.cs" Inherits="GridBulkEdit" EnableViewState="true" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<% /*1. Enter the new value for the column to be updated in the 'NewValue' textbox
2. Check the 'UpdateThisRow' checkbox in the gridview for all rows that need to be updated.
3. Click the 'Update' button */%>
New Value: <asp:TextBox runat="server" ID="NewValue_TextBox"></asp:TextBox>
<asp:Button runat="server" ID="Update_Button" Text="Update Checked Rows With New Value" OnClick="Update_Button_Click" />
<% /* Assuming grid is bound to datasource with 2 columns:
1. 'PrimaryKeyField' - the primary key for each row
2. 'CurrentValue' - the value that we want to batch update */%>
<asp:GridView runat="server" ID="grid" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:HiddenField runat="server" ID="PrmaryKeyForThisRow_HiddenField" Value='<%# Bind("PrimaryKeyField") %>' />
<asp:CheckBox runat="server" ID="UpdateThisRow_CheckBox" Checked="false" ToolTip="Check this box to update this row"/>
<asp:Label runat="server" ID="CurrentValue_Label" Text='<%# Bind("CurrentValue") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Label runat="server" ID="TestOutput_Label"></asp:Label>
</form>
</body>
</html>
GridBulkEdit.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls;
using System.Data;
public partial class GridBulkEdit : System.Web.UI.Page
{
protected void Page_PreInit(object sender, EventArgs e)
{
//Create a data table to bind the grid
DataTable DT = new DataTable();
DT.Columns.Add("PrimaryKeyField");
DT.Columns.Add("CurrentValue");
DataRow DR1 = DT.NewRow();
DR1["PrimaryKeyField"] = 1;
DR1["CurrentValue"] = "value one";
DT.Rows.Add(DR1);
DataRow DR2 = DT.NewRow();
DR2["PrimaryKeyField"] = 2;
DR2["CurrentValue"] = "value two";
DT.Rows.Add(DR2);
DataRow DR3 = DT.NewRow();
DR3["PrimaryKeyField"] = 3;
DR3["CurrentValue"] = "value three";
DT.Rows.Add(DR3);
grid.DataSource = DT;
grid.DataBind();
}
protected void Update_Button_Click(object sender, EventArgs e)
{
TestOutput_Label.Text = "";
for (int i = 0; i < grid.Rows.Count; i++)
{
HiddenField PrmaryKeyForThisRow_HiddenField = grid.Rows[i].FindControl("PrmaryKeyForThisRow_HiddenField") as HiddenField;
CheckBox UpdateThisRow_CheckBox = grid.Rows[i].FindControl("UpdateThisRow_CheckBox") as CheckBox;
if (UpdateThisRow_CheckBox.Checked)
{
UpdateRow(PrmaryKeyForThisRow_HiddenField.Value);
}
}
}
private void UpdateRow(object PrimaryKey)
{
object NewValue = NewValue_TextBox.Text;
//Execute SQL query to update row with the passed PrimaryKey with the NewValue
TestOutput_Label.Text += "<br/> Update row whose PrimaryKey is: " + PrimaryKey + " with new value: " + NewValue;
}
}
I have a grid view which I am binding with data table. My problem is data table has integer values as 1,2,3,4,5. For all these values I want to bind A,B,C,D,E respectively in grid view. I am using bound fields. I dont know where to modify data coming from data table??
Make that column to Template column and put label
<asp:TemplateField HeaderText="HeaderText">
<ItemTemplate>
<asp:Label ID="lbl" runat="server" ></asp:Label>
</ItemTemplate>
and then you do it in RowDataBound event of Gridview
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRow dr = ((DataRowView)e.Row.DataItem).Row;
if(dr["ColumnName"].ToString() == "1" )
{
((Label)e.Row.FindControl("lbl")).Text = "A";
}
else if(dr["ColumnName"].ToString() == "2" )
{
((Label)e.Row.FindControl("lbl")).Text = "B";
}
................
................
}
}