I created a custom DataGridColumn based on Marcie Robillard's MSDN
Article:
Creating Custom Columns for the ASP.NET Datagrid
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/creatingcustomcolumns.asp
The problem I am having is that the data in the custom datagridcolumn
is not saved to viewstate and after postback, the column does not
contain data.
Any idea's?
I simplified the code so that the error is easy to reproduce.
Here is the code: (notice that the CustomImage that is standalone on
the page and the CustomImage that is embedded in a template column are
visible after postback.)
I can send a zip file of the project on request.
-=-=-=-=- CustomColumn.cs (begin) -=-=-=-=-
using System;
using System.Data;
using System.Web.UI.WebControls;
using System.Web.UI;
namespace PostbackError
{
public class CustomColumn : System.Web.UI.WebControls.DataGridColumn
{
public override void
InitializeCell(System.Web.UI.WebControls.TableCell cell, int
columnIndex, System.Web.UI.WebControls.ListItemType itemType)
{
//if the grid is using sorting, the the header will contain a
DataGridLinkButton
//the functionality is set by the base class initializecell.
base.InitializeCell (cell, columnIndex, itemType);
switch (itemType)
{
case ListItemType.Item:
case ListItemType.AlternatingItem:
cell.DataBinding += new EventHandler(OnDataBinding);
break;
}}
private void OnDataBinding(object sender, EventArgs e)
{
TableCell cell = sender as TableCell;
DataGridItem dgi = cell.NamingContainer as DataGridItem;
DataRowView drv = dgi.DataItem as DataRowView;
//hardcoded for this example
string image = "arrow.gif";
if (image.Length == 0)
return;
CustomImage ri = new CustomImage();
cell.Controls.Add(ri);
TrackViewState();
string tooltip = "Help";
ri.ImageUrl = image;
ri.ToolTip = tooltip;
}}}
-=-=-=-=- CustomColumn.cs (end) -=-=-=-=-
-=-=-=-=- CustomImage.cs (begin) -=-=-=-=-
using System;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Web.UI.Design;
namespace PostbackError
{
public class CustomImage : System.Web.UI.WebControls.Image
{
private string _imagePath = string.Empty;
public CustomImage():base()
{
_imagePath = string.Empty;
}
[
Browsable(true),
Category("Appearance"),
Description("Image to be displayed when the mouse is not over the
image")
]
public new string ImageUrl
{
get { return (string)ViewState["riImageUrl"]; }
set { ViewState["riImageUrl"] = value; }
}
[
Browsable(true),
Category("Appearance"),
Description("Image to be displayed when the mouse is over the
image")
]
public string MouseOverImageUrl
{
get { return (string)ViewState["MouseOverImageUrl"]; }
set { ViewState["MouseOverImageUrl"] = value; }
}
[
Browsable(true),
Category("Navigation"),
Description("The url to navigate to")
]
public string NavigateUrl
{
get { return (string)ViewState["NavigateUrl"]; }
set { ViewState["NavigateUrl"] = value; }
}
[
Browsable(true),
Category("Appearance"),
DefaultValue(true),
Description("Use a MouseOver Image derived from the Image name.
(i.e. image.gif -> image_ovr.gif)")
]
public bool UseMouseOverImage
{
get
{
string property = "UseMouseOverImage";
if (ViewState[property] == null)
{
object obj = _GetDefaultValue(property);
if (obj != null)
ViewState[property] = (bool)obj;
}
return (bool)ViewState[property];
}
set { ViewState["UseMouseOverImage"] = value; }
}
override protected void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
string s = base.ImageUrl;
base.ImageUrl = _imagePath + ImageUrl;
s = base.ImageUrl;
string mouseOver = _GetImageMouseOver();
if (mouseOver != null && UseMouseOverImage)
{
Attributes.Add("onmouseover", "this.src='" + _imagePath +
mouseOver + "'");
Attributes.Add("onmouseout", "this.src='" + _imagePath + ImageUrl
+ "'");
}
}
/// <summary>
/// Render this control to the output parameter specified.
/// </summary>
/// <param name="output"> The HTML writer to write out to </param>
protected override void Render(HtmlTextWriter output)
{
bool bWriteAnchor = NavigateUrl != null && NavigateUrl.Length > 0;
string s1 = base.ImageUrl;
base.ImageUrl = _imagePath + ImageUrl;
StringWriter sw = new StringWriter();
HtmlTextWriter buffer = new HtmlTextWriter(sw);
if (bWriteAnchor)
{
buffer.AddAttribute(HtmlTextWriterAttribute.Href, NavigateUrl);
buffer.RenderBeginTag(HtmlTextWriterTag.A);
}
base.Render(buffer);
if (bWriteAnchor)
buffer.RenderEndTag();
string s = sw.ToString();
output.Write(s);
}
private object _GetDefaultValue(string propertyName)
{
System.ComponentModel.AttributeCollection attributes =
TypeDescriptor.GetProperties(this)[propertyName].Attributes;
DefaultValueAttribute myAttribute =
(DefaultValueAttribute)attributes[typeof(DefaultValueAttribute)];
if (myAttribute != null)
return myAttribute.Value;
else
return null;
}
private string _GetImageMouseOver()
{
if (MouseOverImageUrl != null) return MouseOverImageUrl;
StringBuilder sb = new StringBuilder();
Regex re = new Regex(@"\.");
//Image should be like "media.gif" over image should be
"media_ovr.gif"
//and have a part left and right of the period
//if the entry is not in this format, then the entry is invalid
//so return null
if (ImageUrl == null) return null;
string[] sa = re.Split(ImageUrl);
if (sa.Length != 2) return null;
return sa[0] + "_ovr." + sa[1];
}
}
public class CustomImageDesigner:ControlDesigner
{
public override string GetDesignTimeHtml( )
{
return "<h6>" + this.ID + "</h6>";
}
}
}
-=-=-=-=- CustomImage.cs (end) -=-=-=-=-
-=-=-=-=- WebForm1.aspx (begin) -=-=-=-=-
<%@ Register TagPrefix="cust" Namespace="PostbackError"
Assembly="PostbackError" %>
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs"
AutoEventWireup="false" Inherits="PostbackError.WebForm1"
trace="true"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="
http://schemas.microsoft.com/intellisense/ie5"> </HEAD>
<body>
<form id="Form1" method="post" runat="server">
<br>
<cust:CustomImage id="ciTest" runat="server" ImageUrl="arrow.gif"