Extending a (ASP.NET) BoundField - asp.net

I would like to create a control that extends the BoundField that's used within a GridView. What I'd like to do is provide another property named HighlightField that will be similar to the DataField property in that I want to give it the name a data column. Given that data column it would see if the value is true or false and highlight the given text within the given column on the given row.
Some psuedo-code if that doesn't make sense:
<asp:GridView id="grid">
<Columns>
<asp:BoundField DataField="Name" />
<cc:HighlightField DataField="Name" HighlightField="IsHighlighted" />
</Columns>
</asp:GridView>
And then within the databind or something:
if(this row's IsHighlighted value is true)
set the CssClass of this datacell = "highlighted"
(or wrap a span tag around the text)
Ravish pointed me in the correct direction, here's what I ended up with:
public class HighlightedBoundField : BoundField
{
public string HighlightField
{
get { return ViewState["HighlightField"].ToString(); }
set
{
ViewState["HighlightField"] = value;
OnFieldChanged();
}
}
public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
{
base.InitializeCell(cell, cellType, rowState, rowIndex);
bool isDataRowAndIsHighlightFieldSpecified = cellType == DataControlCellType.DataCell && !string.IsNullOrEmpty(HighlightField);
if (isDataRowAndIsHighlightFieldSpecified)
{
cell.DataBinding += new EventHandler(cell_DataBinding);
}
}
void cell_DataBinding(object sender, EventArgs e)
{
TableCell cell = (TableCell)sender;
object dataItem = DataBinder.GetDataItem(cell.NamingContainer);
cell.Text = DataBinder.GetPropertyValue(dataItem, DataField).ToString();
bool highlightThisCellsText = Convert.ToBoolean(DataBinder.GetPropertyValue(dataItem, HighlightField));
if (highlightThisCellsText)
{
cell.CssClass += " highlight";
}
}
}

Untested:
public class HighlightBoundField : DataControlField {
//property to indicate if this field should be highlighted, given the value of this property
//
public string HighlightField {
get {
object value = ViewState["HighlightField"];
if (value != null) {
return Convert.ToString(value);
}
return "";
}
set {
ViewState["HighlightField"] = value;
OnFieldChanged();
}
}
//property to display as text in the cell
//
public string DataField {
get {
object value = ViewState["DataField"];
if (value != null) {
return value.ToString();
}
return string.Empty;
}
set {
ViewState["DataField"] = value;
OnFieldChanged();
}
}
//bound field creation
//
protected override DataControlField CreateField() {
return new BoundField();
}
//override the method that is used to populate and format a cell
//
public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex) {
base.InitializeCell(cell, cellType, rowState, rowIndex);
//if this celltype is a data row
//
if (cellType == DataControlCellType.DataCell && !string.IsNullOrEmpty(HighlightField)) {
//create label control to display text
//
var lblText = new Label();
//add event listener for when the label is bound
//
lblText.DataBinding += new EventHandler(lblText_DataBinding);
//add label to controls collection
//
cell.Controls.Add(lblText);
}
}
void lblText_DataBinding(object sender, EventArgs e) {
//retrieve data item and set label text
//
Label lblText = (Label) sender;
object dataItem = DataBinder.GetDataItem(lblText.NamingContainer);
lblText.Text = DataBinder.GetPropertyValue(dataItem, DataField).ToString();
//check if value should be highlighted
//
if (Convert.ToBoolean(DataBinder.GetPropertyValue(dataItem, HighlightField))) {
lblText.Style.Add("background-color", "yellow");
}
}
}

Related

GridView dynamic Controls are emptied upon clicking edit/update/delete buttons. Asp.net

I have a gridview that is being dynamically populated using a custom template, but the command fields are static. Upon clicking the command fields, the controls are understandably lost. This problem doesn't affect me during edit, because once the gridview is rebound, it would know it is in edit mode and create the dynamic edit template fields. But once I make changes to these fields, which are textboxes, I would need to click on the Update command field to instantiate my update method. Upon clicking, the controls are immediately lost, so in my update method I cannot find the controls to which changes have been made. Any ideas how to solve this? I will post code if needed.
The Grid View Template. Here is where the databindings happen upon dynamic generation. Getting the data from the table and reproducing it on the grid view works fine.
public class GridViewTemplate : System.Web.UI.Control, System.Web.UI.ITemplate
{
// static attributes here
// constructor
public GridViewTemplate(DataControlRowType type, string columnName, string categoryID, string itemControl, string editControl, string footerControl, string dataBinds)
{
DataRowType = type; // Header, DataRow,
st_columnName = columnName; // Header name
st_categoryId = categoryID;
if (itemControl != null)
st_itemControl = itemControl.ToUpper(); // Control type for Item Template
if (editControl != null)
st_editControl = editControl.ToUpper(); // Control type for Edit Template
if (footerControl != null)
st_footerControl = footerControl.ToUpper(); // Control type for Footer Template
if (dataBinds != null)
st_dataBinds = dataBinds;
}
public void InstantiateIn(Control container)
{
switch (DataRowType)
{
case DataControlRowType.Header:
{
// Build the header for this column
Label lb_header = new Label();
lb_header.Text = "<b>" + st_columnName + "</b>";
lb_header.ID = st_categoryId;
container.Controls.Add(lb_header);
}
break;
case DataControlRowType.DataRow:
{
if (Regex.IsMatch(st_categoryId,"^(xxI_)")) // item mode
{
if (st_itemControl.Equals(LABEL))
{
// For Label
}
else if (st_itemControl.Equals(TEXTBOX))
{
TextBox dcrt_textbox = new TextBox();
dcrt_textbox.ID = st_categoryId;
dcrt_textbox.Visible = true;
dcrt_textbox.Enabled = false;
dcrt_textbox.DataBinding += new EventHandler(this.TextBox_DataBinding);
container.Controls.Add(dcrt_textbox);
}
else if (st_itemControl.Equals(CHECKBOX))
{
// For checkbox
}
}
else if (Regex.IsMatch(st_categoryId, "^(xxE_)")) // edit mode
{
if (st_editControl.Equals(LABEL))
{
// For label
}
else if (st_editControl.Equals(TEXTBOX))
{
TextBox dcrt_textbox = new TextBox();
dcrt_textbox.ID = st_categoryId;
dcrt_textbox.Visible = true;
dcrt_textbox.EnableViewState = true;
dcrt_textbox.AutoPostBack = false;
dcrt_textbox.ViewStateMode = ViewStateMode.Enabled;
dcrt_textbox.DataBinding += new EventHandler(this.TextBox_DataBinding);
container.Controls.Add(dcrt_textbox);
}
else if (st_editControl.Equals(CHECKBOX))
{
// For checkbox
}
}
}
break;
case DataControlRowType.EmptyDataRow:
// To be implemented when necessary
break;
case DataControlRowType.Pager:
// To be implemented when necessary
break;
case DataControlRowType.Separator:
// To be implemented when necessary
break;
default:
break;
}
}
public void TextBox_DataBinding(Object sender, EventArgs e)
{
TextBox tb_databound = (TextBox)sender;
GridViewRow row = (GridViewRow)tb_databound.NamingContainer;
string RawValue = DataBinder.Eval(row.DataItem, st_columnName).ToString();
tb_databound.Text = RawValue;
}
public void Label_DataBinding(Object sender, EventArgs e)
{
Label lb_databound = (Label)sender;
GridViewRow row = (GridViewRow)lb_databound.NamingContainer;
string RawValue = DataBinder.Eval(row.DataItem, st_columnName).ToString();
lb_databound.Text = RawValue;
}
public void CheckBox_DataBinding(Object sender, EventArgs e)
{
CheckBox cb_databound = (CheckBox)sender; // get the control that raised this event
GridViewRow row = (GridViewRow)cb_databound.NamingContainer; // get the containing row
string RawValue = DataBinder.Eval(row.DataItem, st_columnName).ToString();
if (RawValue.ToUpper().Equals("TRUE"))
{
cb_databound.Checked = true;
}
else
{
cb_databound.Checked = false;
}
}
}
}
The onEdit and onUpdate methods.
protected void onRowEditing(object sender, GridViewEditEventArgs e)
{
gv.EditIndex = e.NewEditIndex;
tableBind(ViewState["table"]); // View state contains the table, which is then passed to a bind method that binds the gridview.
}
protected void onRowUpdating(object sender, GridViewUpdateEventArgs e)
{
GridViewRow row = gv_rebateTable.Rows[e.RowIndex];
// at this point, xxE_tier (a textbox in edit mode) was destroyed
TextBox tb = row.FindControl("xxE_tier") as TextBox;
}
Gridview:
<asp:GridView ID="gv" EnableViewState="true" ViewStateMode="Enabled" OnRowEditing="onRowEditing" OnRowCancelingEdit="onRowCancelingEdit" OnRowUpdating="onRowUpdating" OnRowDeleting="onRowDeleting" EnableModelValidation="true" ShowFooter="true" OnRowCommand="onRowCommand" AutoGenerateColumns="False" runat="server">
<Columns>
<asp:ButtonField Text="Analysis" ButtonType="Button" HeaderText="" ShowHeader="True" />
<asp:CommandField EditText="Edit" ButtonType="Button" HeaderText="" ShowEditButton="True" ShowHeader="True" ValidationGroup="Edit_Group"/>
<asp:CommandField EditText="Delete" ButtonType="Button" HeaderText="" ShowDeleteButton="True" ShowHeader="True" />
</Columns>
</asp:GridView>

How to access a gridview column on rowdatabound ?

I would like to change the value of my gridview column to active when the value is 1.
I have gridview column like
<asp:BoundField DataField="STATUS" HeaderText="STATUS" SortExpression="STATUS" HeaderStyle-HorizontalAlign="Left">
<HeaderStyle HorizontalAlign="Left"></HeaderStyle>
</asp:BoundField>
and cs code
protected void gvCategory_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.Cells[5].Text=="0")
{
e.Row.Cells[5].Text = "INACTIVE";
}
}
}
This is working but it would fail if i change the column order.
What i need is something like findControl function.
Thanks.
Here's a few utilities I wrote years ago that may help you:
// ---- GetCellByName ----------------------------------
//
// pass in a GridViewRow and a database column name
// returns a DataControlFieldCell or null
static public DataControlFieldCell GetCellByName(GridViewRow Row, String CellName)
{
foreach (DataControlFieldCell Cell in Row.Cells)
{
if (Cell.ContainingField.ToString() == CellName)
return Cell;
}
return null;
}
// ---- GetColumnIndexByHeaderText ----------------------------------
//
// pass in a GridView and a Column's Header Text
// returns index of the column if found
// returns -1 if not found
static public int GetColumnIndexByHeaderText(GridView aGridView, String ColumnText)
{
TableCell Cell;
for (int Index = 0; Index < aGridView.HeaderRow.Cells.Count; Index++)
{
Cell = aGridView.HeaderRow.Cells[Index];
if (Cell.Text.ToString() == ColumnText)
return Index;
}
return -1;
}
// ---- GetColumnIndexByDBName ----------------------------------
//
// pass in a GridView and a database field name
// returns index of the bound column if found
// returns -1 if not found
static public int GetColumnIndexByDBName(GridView aGridView, String ColumnText)
{
System.Web.UI.WebControls.BoundField DataColumn;
for (int Index = 0; Index < aGridView.Columns.Count; Index++)
{
DataColumn = aGridView.Columns[Index] as System.Web.UI.WebControls.BoundField;
if (DataColumn != null)
{
if (DataColumn.DataField == ColumnText)
return Index;
}
}
return -1;
}
You could loop all columns to get the correct index or use this LINQ:
String colToFind = "status";
int colIndex = ((GridView)sender).Columns.Cast<DataControlField>()
.Where((c, index) => c.HeaderText.ToLower().Equals(colToFind))
.Select((c,index)=>index).First();
Cleaner easier to read LINQ. Tim's did not work for me.
private int GetFirstGridViewColIndex(string dataField, object sender)
{
var boundFieldColumns = ((GridView)sender).Columns.Cast<BoundField>();
return boundFieldColumns.Where((column, index) => string.Equals(column.DataField, dataField, StringComparison.InvariantCultureIgnoreCase))
.Select((column, index) => index)
.First();
}

How to maintain state in (asp.net) custom server control?

I am trying to make a custom server control which inherits from DropDownList. I give the control an XML input containing some key/value pairs and my control shows them as a DropDownList.
I make the list items in the override Render method like this:
foreach (XElement child in root.Elements("Choice"))
{
string title = child.Element("Title").Value;
string score = child.Element("Score").Value;
item = new ListItem();
item.Text = title;
item.Value = score;
this.Items.Add(item);
}
The problem is that, when the user selects and item in the list, and the page posts back, the selected item is lost, and the list is re-initialized with the default data.
Does anyone have any idea how to keep the selected item, i.e. maintain the state?
Here is the complete source:
public class MultipleChoiceQuestionView2 : DropDownList
{
public MultipleChoiceQuestionView2() : base()
{
}
protected override void Render(HtmlTextWriter writer)
{
writer.RenderBeginTag(HtmlTextWriterTag.Table);
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
#region Parse Contets
if (!String.IsNullOrEmpty(this.Contents))
{
XElement root = XElement.Parse(this.Contents);
if (root.HasAttributes)
{
this.NoOfChoices = Int32.Parse(root.Attribute("ItemCount").Value);
}
this.Items.Clear();
this.Style.Add("width", "100px");
this.Style.Add("font-family", "Tahoma");
this.Items.Clear();
ListItem item = new ListItem();
item.Text = "";
item.Value = "0";
this.Items.Add(item);
foreach (XElement child in root.Elements("Choice"))
{
string title = child.Element("Title").Value;
string score = child.Element("Score").Value;
item = new ListItem();
item.Text = title;
item.Value = score;
this.Items.Add(item);
}
}
#endregion
base.Render(writer);
writer.RenderEndTag();
if (this.Required)
{
RequiredFieldValidator rfv = new RequiredFieldValidator();
rfv.ControlToValidate = this.ID;
rfv.InitialValue = "0";
rfv.Text = "*";
if (!String.IsNullOrEmpty(this.ValidationGroup))
{
rfv.ValidationGroup = this.ValidationGroup;
}
writer.RenderBeginTag(HtmlTextWriterTag.Td);
rfv.RenderControl(writer);
writer.RenderEndTag();
}
writer.RenderEndTag();
writer.RenderEndTag();
}
#region Properties
public string Contents
{
get
{
return ViewState["Contents"] == null ? "" : ViewState["Contents"].ToString();
}
set
{
ViewState["Contents"] = value;
}
}
private int mNoOfChoices;
public int NoOfChoices
{
get
{
return mNoOfChoices;
}
set
{
mNoOfChoices = value;
}
}
private string mValidationGroup;
public string ValidationGroup
{
get
{
return mValidationGroup;
}
set
{
mValidationGroup = value;
}
}
public string SelectedChoice
{
get
{
return "";
}
}
private bool mRequired = false;
public bool Required
{
get
{
return mRequired;
}
set
{
mRequired = value;
}
}
#endregion
}
Thanks in advance.
You've got two options: ViewState or ControlState.
The difference being ViewState can be overriden by setting EnableViewState="false" in the page directive, whilst ControlState cannot.
Essentially you need to hook into the state bag when you're getting/setting the values of the dropdown.
There's a decent example here where a custom control is derived from the Button class and maintains state between page requests - should fit your scenario nicely.
Hopefully that gets you started.

Validation controls not applicable to web custom controls in asp.net

I have created a web custom control and used within an aspx page. I found the validation controls provided by asp.net are applicable to the built in server controls. I am not able to attach these validation controls with my custom control.
For ex. If i am using TextBox control then the RequiredFieldValidator is applicable to it. but when i try to apply the same RequiredFieldValidator to my custom control it is not possible. The property "ControlToValidate" does not show the object id of my custom control.
Could someone help me to rectify this problem?
Thanks for sharing your valuable time.
Below is the code from .cs file -
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Security.Permissions;
[assembly: TagPrefix("DatePicker", "SQ")]
namespace DatePicker
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:DatePicker runat=server></{0}:DatePicker>")]
public class DatePicker : CompositeControl
{
//To retrieve value i am using textbox
private TextBox _TxtDate = new TextBox();
// Image to select the calender date
private Image _ImgDate = new Image();
// Image URL to expose the image URL Property
private string _ImageUrl;
// Exposing autopostback property
private bool _AutoPostBack;
// property get the value from datepicker.
private string _Value;
//CSS class to design the Image
private string _ImageCssClass;
//CSS class to design the TextBox
private string _TextBoxCssClass;
//to formate the date
private string _DateFormat = "%m/%d/%Y";
//to hold javascript on client side
static Literal _litJScript=new Literal();
private bool _includeJS = false;
/**** properties***/
#region "[ Properties ]"
[Bindable(true), Category("Appearance"), DefaultValue("")]
public string ImageUrl
{
set
{
this._ImageUrl = value;
}
}
[Bindable(true), Category("Appearance"), DefaultValue(""), Localizable(true)]
public string Text
{
get
{
//String s = (String)ViewState["Text"];
//return ((s == null) ? string.Empty : s);
return _Value = _TxtDate.Text;
}
set
{
ViewState["Text"] = value;
_TxtDate.Text = value;
_TxtDate.BackColor = System.Drawing.Color.White;
}
}
[Bindable(true), Category("Appearance"), DefaultValue(""), Localizable(true)]
public string Value
{
get
{
return _Value= _TxtDate.Text;
}
set
{
_Value = _TxtDate.Text = value;
ViewState["Text"] = _Value;
_TxtDate.BackColor = System.Drawing.Color.White;
}
}
[Bindable(true), Category("Appearance"), DefaultValue(""), Localizable(true)]
public bool AutoPostBack
{
get
{
return _AutoPostBack;
}
set
{
_AutoPostBack = value;
}
}
[Bindable(true), Category("Appearance"), DefaultValue(""), Localizable(true)]
public string ImageCssClass
{
get
{
return _ImageCssClass;
}
set
{
_ImageCssClass = value;
}
}
[Bindable(true), Category("Appearance"), DefaultValue(""), Localizable(true)]
public string TextBoxCssClass
{
get
{
return _TextBoxCssClass;
}
set
{
_TextBoxCssClass = value;
}
}
[Bindable(true), Category("Custom"), DefaultValue(""), Localizable(true)]
public string CommandName
{
get
{
string s = ViewState["CommandName"] as string;
return s == null ? String.Empty : s;
}
set
{
ViewState["CommandName"] = value;
}
}
[Bindable(true), Category("Custom"), DefaultValue(""), Localizable(true)]
public string CommandArgument
{
get
{
string s = ViewState["CommandArgument"] as string;
return s == null ? String.Empty : s;
}
set
{
ViewState["CommandArgument"] = value;
}
}
[Bindable(true), Category("Custom"), DefaultValue(""), Localizable(true)]
public string DateFormat
{
get
{
return _DateFormat;
}
set
{
_DateFormat = value;
}
}
[Bindable(true), Category("Behavior"), DefaultValue("True")]
public bool IncludeClientSideJS
{
get { return _includeJS; }
set {
_includeJS = value;
}
}
[Bindable(true), Category("Behavior"), DefaultValue("True")]
public override bool Enabled
{
get { return _TxtDate.Enabled; }
set
{
_TxtDate.Enabled = value;
_ImgDate.Visible = value;
}
}
[Bindable(true), Category("Layout")]
public override Unit Width
{
get
{
return base.Width;
}
set
{
base.Width = value;
_TxtDate.Width = value;
}
}
#endregion
protected static readonly object EventCommandObj = new object();
public event CommandEventHandler Command
{
add
{
Events.AddHandler(EventCommandObj, value);
}
remove
{
Events.RemoveHandler(EventCommandObj, value);
}
}
//this will raise the bubble event
protected virtual void OnCommand(CommandEventArgs commandEventArgs)
{
CommandEventHandler eventHandler = (CommandEventHandler)Events[EventCommandObj];
if (eventHandler != null)
{
eventHandler(this, commandEventArgs);
}
base.RaiseBubbleEvent(this, commandEventArgs);
}
//this will be initialized to OnTextChanged event on the normal textbox
private void OnTextChanged(object sender, EventArgs e)
{
if (this.AutoPostBack)
{
//pass the event arguments to the OnCommand event to bubble up
CommandEventArgs args = new CommandEventArgs(this.CommandName, this.CommandArgument);
OnCommand(args);
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
AddStyleSheet();
AddJavaScript("DatePicker.Resources.prototype.js");
AddJavaScript("DatePicker.Resources.calendarview.js");
// For TextBox
// setting name for textbox. using t just to concat with this.ID for unqiueName
_TxtDate.ID = this.ID + "t";
// setting postback
_TxtDate.AutoPostBack = this.AutoPostBack;
// giving the textbox default value for date
_TxtDate.Text = this.Value;
//Initializing the TextChanged with our custom event to raise bubble event
_TxtDate.TextChanged += new System.EventHandler(this.OnTextChanged);
//Set max length
_TxtDate.MaxLength = 10;
//Setting textbox to readonly to make sure user dont play with the textbox
//_TxtDate.Attributes.Add("readonly", "readonly");
// adding stylesheet
_TxtDate.Attributes.Add("class", this.TextBoxCssClass);
_TxtDate.Attributes.Add("onkeypress", "maskDate(event)");
_TxtDate.Attributes.Add("onfocusout","isValidDate(event)");
// For Image
// setting alternative name for image
_ImgDate.AlternateText = "imageURL";
if (!string.IsNullOrEmpty(_ImageUrl))
_ImgDate.ImageUrl = _ImageUrl;
else
{
_ImgDate.ImageUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(), "DatePicker.Resources.CalendarIcon.gif");
}
//setting name for image
_ImgDate.ID = this.ID + "i";
//setting image class for textbox
_ImgDate.Attributes.Add("class", this.ImageCssClass);
//Initialize JS with literal
string s = "<script language=\"javascript\">function maskDate(e){var evt=window.event || e;var srcEle = evt.srcElement?e.srcElement:e.target;";
s = s + "var myT=document.getElementById(srcEle.id);var KeyID = evt.keyCode;";
s = s + "if((KeyID>=48 && KeyID<=57) || KeyID==8){if(KeyID==8)return;if(myT.value.length==2){";
s = s + "myT.value=myT.value+\"/\";}if(myT.value.length==5){myT.value=myT.value+\"/\";}}";
s = s + "else{window.event.keyCode=0;}}";
string s1 = "function isValidDate(e){var validDate=true;var evt=window.event || e;var srcEle = evt.srcElement?e.srcElement:e.target;";
s1 = s1 + "var myT=document.getElementById(srcEle.id);var mm=myT.value.substring(0,2);var dd=myT.value.substring(5,3);var yy=myT.value.substring(6);";
s1 = s1 + "var originalCss =myT.className; if(mm!=0 && mm>12){myT.value=\"\"; validDate=false;}else{if((yy % 4 == 0 && yy % 100 != 0) || yy % 400 == 0){if(mm==2 && dd>29){";
s1 = s1 + "myT.value=\"\"; validDate=false;}}else{if(mm==2 && dd>28){myT.value=\"\"; validDate=false;}else{if(dd!=0 && dd>31){";
s1 = s1 + "myT.value=\"\"; validDate=false;}else{if((mm==4 || mm==6 || mm==9 || mm==11) && (dd!=0 && dd>30)){myT.value=\"\"; validDate=false;}}}}}";
s1 = s1 + "if(!validDate){myT.style.backgroundColor='#FD9593';myT.focus;}else { myT.style.backgroundColor='#FFFFFF';}}</script>";
_litJScript.Text = s+s1;
}
/// <summary>
/// adding child controls to composite control
/// </summary>
protected override void CreateChildControls()
{
this.Controls.Add(_TxtDate);
this.Controls.Add(_ImgDate);
if(_includeJS)
this.Controls.Add(_litJScript);
base.CreateChildControls();
}
public override void RenderControl(HtmlTextWriter writer)
{
//render textbox and image
_TxtDate.RenderControl(writer);
_ImgDate.RenderControl(writer);
if(_includeJS)
_litJScript.RenderControl(writer);
RenderContents(writer);
}
/// <summary>
/// Adding the javascript to render the content
/// </summary>
/// <param name="output"></param>
protected override void RenderContents(HtmlTextWriter output)
{
StringBuilder calnder = new StringBuilder();
//adding javascript first
if (Enabled)
{
calnder.AppendFormat(#"<script type='text/javascript'>
document.observe('dom:loaded', function() {{
Calendar.setup({{
dateField: '{0}',
triggerElement: '{1}',
dateFormat: '{2}'
}})
}});
", _TxtDate.ClientID, _ImgDate.ClientID, _DateFormat);
calnder.Append("</script>");
}
else
{
calnder.AppendFormat(#"<script type='text/javascript'>
document.observe('dom:loaded', function() {{
Calendar.setup({{
dateField: '{0}',
triggerElement: '{1}',
dateFormat: '{2}'
}})
}});
", _TxtDate.ClientID, null, _DateFormat);
calnder.Append("</script>");
}
output.Write(calnder.ToString());
}
private void AddStyleSheet()
{
string includeTemplate = "<link rel='stylesheet' text='text/css' href='{0}' />";
string includeLocation =
Page.ClientScript.GetWebResourceUrl(this.GetType(), "DatePicker.Resources.calendarview.css");
LiteralControl include = new LiteralControl(String.Format(includeTemplate, includeLocation));
Page.Header.Controls.Add(include);
}
private void AddJavaScript(string javaScriptFile)
{
string scriptLocation = Page.ClientScript.GetWebResourceUrl(this.GetType(),javaScriptFile );
Page.ClientScript.RegisterClientScriptInclude(javaScriptFile, scriptLocation);
}
}
}
You should either use a CustomValidator, or insert the RequiredFieldValidator directly into your custom control. Of course the built-in validators don't work with your control... they have no idea what to do with it! But if your control internally uses a TextBox, then you can also have a RequiredFieldValidator there.
A third possibility is to expose your internal TextBox with a property, which you can then reference with ControlToValidate. However, the first two methods are preferable.
I'm having the same problem and I solved it by adding the attribute [ValidationPropertyAttribute("Text")] to my custom webcontrol class.
The specified value must correspond to the property to validate (see https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.validationpropertyattribute?view=netframework-4.7.2 for more informations).

How can I change the field type on a GridView at runtime with AutoGenerate="True"?

I've created a control that extends the BoundField control to do some special processing on the data that's passed into it.
I now have a grid that has AutoGenerateColumns="true", by which I'd like to intercept the HeaderText, see if it's a particular value and then swap in the "SpecialBoundField" instead. I've tried using the OnDataBinding event to loop through the columns, but at this point there are no columns in the grid. I think that RowDataBound and DataBound are too late in the game so not sure what to do.
My next thought was to override the grid control itself to add in a "AutoGeneratingColumn" event in
protected virtual AutoGeneratedField CreateAutoGeneratedColumn(AutoGeneratedFieldProperties fieldProperties)
Can anyone help or point me in a better direction? Thanks!
If you have both fields coming back in the dataset, I would suggest setting the column visibilities instead of trying to dynamically add or change the datafields. Invisible columns don't render any HTML, so it would just be a matter of looking at the header row when it gets bound, checking the field you're interested in, and setting the column visibility.
void myGridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
if (e.Row.Cells[1].Text = "BadText")
{
myGridView.Columns[1].Visible = false;
myGridView.Columns[5].Visible = true;
}
}
}
What I ended up with:
public class SpecialGridView : GridView
{
protected override void OnRowDataBound(GridViewRowEventArgs e)
{
ModifyData(e);
base.OnRowDataBound(e);
}
IList<string> _columnNames = new List<string>();
protected void ModifyData(GridViewRowEventArgs e)
{
LoadColumnNames(e);
if (e.Row.RowType == DataControlRowType.DataRow)
{
for (int i = 0; i < e.Row.Cells.Count; i++)
{
string currentColumnName = _columnNames[i];
if (IsSpecialColumn(currentColumnName))
{
string text = e.Row.Cells[0].Text;
bool isSpecialData = text.ToUpper() == "Y";
if (isSpecialData)
{
e.Row.Cells[i].CssClass += " specialData";
}
}
}
}
}
private void LoadColumnNames(GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
foreach (TableCell cell in e.Row.Cells)
{
_columnNames.Add(cell.Text);
}
}
}
private bool IsSpecialColumn(string currentColumnName)
{
foreach (string columnName in SpecialColumnNames)
{
if (currentColumnName.ToUpper() == columnName.ToUpper())
{
return true;
}
}
return false;
}
private IList<string> _specialColumnNames = new List<string>();
public IList<string> SpecialColumnNames
{
get { return _specialColumnNames; }
set { _specialColumnNames = value; }
}
}

Resources