Reputation: 7114
I am creating a DataTable at runtime. My goal is to insert an image into the DataTable to ultimately be displayed in a GridView. The answer HERE looked promising, but I copy and pasted it into VS and it simply doesn't work. By "doesn't work," I mean that when I go to display the DataTable in a GridView, the cell that should contain the picture simply contains the string, "System.Byte[]"
Here is a very abbreviated version of the construction and population of the DataTable:
DataTable dt = new DataTable();
DataColumn imagecol = new DataColumn();
dt.Columns.Add(imagecol);
DataRow newrow;
for (int x = 0, x < 10; x++)
{
newrow = dt.NewRow();
newrow[imagecol] = *********
dt.Add(newrow);
}
The * part is where I keep failing.
I never use the .aspx fields for the GridView (ImageField, TemplateField, etc.), so I'm looking for solutions that don't require editting the .aspx code or "preparing" the GridView for a DataTable with specific columns. Let me just answer before someone asks. My reasons for this are:
A) I only ever learned how to make a GridView out of a programmatically created DataTable.
B) I don't like that if I want to change my fields at some point, I have to make the edit in TWO places instead of just one.
C) All the other pages of the application use this style, so I want to keep it consistent.
So what have I tried?
DataColumn imagecol = new DataColumn();
imagecol.DataType = System.Type.GetType("System.Byte[]");
//...
newrow[amountcol] = ReadImage(Server.MapPath("~/images/dashboard/myvacstatus-ampm.png"), new string[] { ".png" });
(the ReadImage function converts an image to a byte array)
RESULT: the field in the GridView displays the text "System.Byte[]".
DataColumn imagecol = new DataColumn();
//...
newrow[amountcol] = ResolveUrl("~/images/dashboard/myvacstatus-ampm.png");
RESULT: the field in the GridView displays the text "/images/dashboard/myvacstatus-ampm.png"
DataColumn imagecol = new DataColumn();
//...
Image timeImg = new Image();
timeImg.ImageUrl = "/images/dashboard/myvacstatus-ampm.png"
newrow[amountcol] = timeImg;
RESULT: the field in the GridView displays the text "System.Web.UI.WebControls.Image"
My final requirement is that the field this goes in to must have the flexibility to be an Image, OR a string. To put this in perspective/see what I'm trying to do, this is for a vacation management system. Vacations are generally taken in half-day or whole-days. We have icons for both. But on occasion a vacation can last X number of hours. So in the case that it's exactly a half-day, that row needs the image for half-day. If it's a full-day, that row needs the image for full-day. If the amount of time is neither exactly half nor full, in place of the image, we need to place the number of hours as text.
One possible solution that I think will work is to put the hours of a vacation in a hidden column, then on the RowDataBound event, use the hidden value of hours to create the necessary image or text, and then say like:
e.Row.Cells[3].Controls.Add(myImage);
I don't like this because it splits my code up again, I have to always just know what the Cells index is, etc. I really just want to keep all of it contained my BuildDataTable function.
Upvotes: 0
Views: 12603
Reputation: 9166
Edit: Complete rewite of the answer after re-reading the question.
You state:
I never use the .aspx fields for the GridView (ImageField, TemplateField, etc.), so I'm looking for solutions that don't require editting the .aspx code ...
If you want to only use AutoGenerateColumns="false"
then I don't think you will be able to show an image in the GridView.
In order to show an image, the rendered page will HAVE to have an image tag. No way to get around that, unless you start fiddling around with CSS data urls.
For your requirements that sounds awefully complicated and it will not work in all browsers anyway.
To show the image, I think you will have to manually setup the GridView
. Here's a complete working example that you can use as a starting point (you must adjust the image urls to match your project):
In aspx file:
<asp:GridView ID="example" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:BoundField HeaderText="Some other field" DataField="SomeOtherField" />
<asp:TemplateField HeaderText="Image/Text">
<ItemTemplate>
<asp:Image ID="FullDay" runat="server" Visible='<%# ((int)Eval("HoursField")) == this.FullDayHours %>'
ImageUrl="~/images/dashboard/fullDayImage.png" />
<asp:Image ID="HalfDay" runat="server" Visible='<%# ((int)Eval("HoursField")) == this.HalfDayHours %>'
ImageUrl="~/images/dashboard/halfDayImage.png" />
<asp:Literal ID="ShowHours" runat="server" Visible='<%# ((int)Eval("HoursField")) != this.HalfDayHours && ((int)Eval("HoursField")) != this.FullDayHours %>'
Text='<%# Eval("HoursField") %>'></asp:Literal>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code behind file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.Data;
public partial class GridViewTest : System.Web.UI.Page
{
public readonly int FullDayHours = 8;
public readonly int HalfDayHours = 4;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DataTable gridViewSource = new DataTable();
DataColumn oneColumn = new DataColumn("SomeOtherField");
oneColumn.DataType = System.Type.GetType("System.String");
gridViewSource.Columns.Add(oneColumn);
oneColumn = new DataColumn("HoursField");
oneColumn.DataType = System.Type.GetType("System.Int32");
gridViewSource.Columns.Add(oneColumn);
for (int i = 0; i < 10; i++)
{
DataRow oneRow = gridViewSource.NewRow();
oneRow["SomeOtherField"] = "Other field " + i.ToString();
oneRow["HoursField"] = i;
gridViewSource.Rows.Add(oneRow);
}
example.DataSource = gridViewSource;
example.DataBind();
}
}
}
Upvotes: 2