ASP.NET GridView RowDataBound TemplateField FindControl is null after invalid data entered - asp.net

I am having trouble with my GridView RowDataBound event after I click on Save to save the data to the database.
I have a grid with 5 columns: Tag Name, Current Timestamp, Current Value, New Date, New Value.
The idea is the user will enter into the New Date/New Value to update the data in the database. The Current Timestamp and Current Value are what is already stored in the database.
I use a JQuery editor to enter the date.
When I click on Save, I have server side validation in place to check the entered values. If the data is valid, a message under the text in the New Value column is displayed to indicate this. If the validation fails, then a message in the New Value column is displayed.
New Date and New Value columns are TemplateField's. The New Value TemplateField contains a panel with two labels - one for OK status and the other for error.
The error occurs in MyDataGrid_RowDataBound when I call any e.Row.FindControl(...) which is triggered from the Save button click when I rebind.
It works ok if a valid value has been entered but if an invalid value is entered then it errors. In order to simplify the scenario, enter 100 for a valid value and anything else for an invalid.
This WebForm has been the trouble of my life. Maybe I shouldn't have used a GridView.
Anyway, I would appreciate any help here to identify the issue. And maybe a better approach to the form code.
I've took the code from my solution and moved it into a standalone solution to reproduce the issue. I've removed the database access and populated a datastructure. This is only ever done (once) in the Page Load when the page is initially loaded.
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link rel="stylesheet" href="Styles/jquery-ui-timepicker-addon.css" />
<link rel="stylesheet" href="Styles/jquery-ui-1.10.1.custom.css" />
<link rel="stylesheet" href="Styles/jquery-ui-1.10.1.custom.min.css" />
<script src="Scripts/jquery-1.9.1.js"></script>
<script src="Scripts/jquery-ui-1.10.1.custom.js"></script>
<script src="Scripts/jquery-ui-1.10.1.custom.min.js"></script>
<script src="Scripts/jquery-ui-timepicker-addon.js"></script>
</head>
<body>
<script type="text/javascript">
/** Disable backkey */
$(document).unbind('keydown').bind('keydown', function (event) {
var doPrevent = false;
if (event.keyCode === 8) {
var d = event.srcElement || event.target;
if ((d.tagName.toUpperCase() === 'INPUT' && (d.type.toUpperCase() === 'TEXT' || d.type.toUpperCase() === 'PASSWORD' || d.type.toUpperCase() === 'FILE'))
|| d.tagName.toUpperCase() === 'TEXTAREA') {
doPrevent = d.readOnly || d.disabled;
} else {
doPrevent = true;
}
}
if (doPrevent) {
event.preventDefault();
}
});
$(function () {
$(".datetimepicker").datetimepicker({
changeMonth: true,
changeYear: true
});
});
$(function () {
$(".datepicker").datepicker({
changeMonth: true,
changeYear: true
});
});
$(function () {
$(".timepicker").timepicker({ showTimezone: false });
});
</script>
<form id="form1" runat="server">
<div>
<asp:GridView ID="MyDataGrid" runat="server"
EnableModelValidation="True"
DataKeyNames="Id"
AutoGenerateColumns="False"
AutoGenerateSelectButton="False"
EmptyDataText="There is no plant data configured."
OnRowDataBound="MyDataGrid_RowDataBound">
<Columns>
<asp:BoundField DataField="Name" SortExpression="Name" HeaderText="Tag Name"></asp:BoundField>
<asp:BoundField DataField="Date" SortExpression="Date" HeaderText="Current Timestamp"></asp:BoundField>
<asp:BoundField DataField="Value" SortExpression="Value" HeaderText="Current Value"></asp:BoundField>
<asp:TemplateField HeaderText="New Date<BR/>MM/DD/YYYY HH:MM">
<ItemTemplate>
<asp:TextBox ID="txtNewDate" runat="server" CssClass="datetimepicker"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="New Value">
<ItemTemplate>
<asp:TextBox ID="txtNewValue" runat="server"></asp:TextBox>
<asp:Panel ID="ErrorPanel" runat="server">
<br />
<asp:Label ID="lblError" runat="server" ForeColor="Red"></asp:Label>
<asp:Label ID="lblStatus" runat="server" ForeColor="#66cc00"></asp:Label>
</asp:Panel>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Button ID="SaveButton" runat="server"
Text="Save Values"
ToolTip="Save the current changes."
OnClick="SaveButton_Click" />
</div>
</form>
</body>
</html>
Code Behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
private const int COL_NEW_DATE = 3;
private const int COL_NEW_VALUE = 4;
bool canEdit = true;
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
PopulateDataGrid();
}
}
private void PopulateDataGrid()
{
// this is where i load from the database
List<RowData> data = new List<RowData>() {
new RowData() { Date = new DateTime(2000,1,1), Editable = true, Name = "Data Item 1", Value = 100.0 },
new RowData() { Date = new DateTime(2000,1,1), Editable = false, Name = "Data Item 2", Value = 120.0 },
new RowData() { Date = new DateTime(2000,1,1), Editable = true, Name = "Data Item 3", Value = 19.0 }
};
this.MyDataGrid.DataSource = data;
this.MyDataGrid.DataBind();
ViewState["GridData"] = this.MyDataGrid.DataSource;
}
private void SaveData()
{
for (int i = Page.Validators.Count - 1; i >= 0; i--)
Page.Validators.Remove(Page.Validators[i]);
ValidateData();
List<RowData> rowDataList = (List<RowData>)ViewState["GridData"];
if (this.IsValid)
{
foreach (GridViewRow row in this.MyDataGrid.Rows)
{
if (row.RowType == System.Web.UI.WebControls.DataControlRowType.DataRow && row.Enabled)
{
RowData dataItem = rowDataList[row.DataItemIndex];
var txtNewValue = row.Cells[COL_NEW_VALUE].FindControl("txtNewValue") as TextBox;
var txtNewDate = row.Cells[COL_NEW_DATE].FindControl("txtNewDate") as TextBox;
if (dataItem != null && txtNewDate != null && txtNewValue != null && !string.IsNullOrEmpty(txtNewValue.Text) && !string.IsNullOrEmpty(txtNewDate.Text))
{
var newValue = double.Parse(txtNewValue.Text);
var newDate = DateTime.Parse(txtNewDate.Text);
dataItem.InfoText = "Value written successfully for " + txtNewDate.Text;
dataItem.ErrorText = string.Empty;
dataItem.EnteredDateCache = string.Empty;
dataItem.EnteredValueCache = string.Empty;
if ((dataItem.Date.HasValue && DateTime.Compare(newDate, dataItem.Date.Value) >= 0) || !dataItem.Date.HasValue)
{
dataItem.Date = newDate;
dataItem.Value = newValue;
}
}
}
}
// save any outstanding changes if valid removed from demo
}
ViewState["GridData"] = rowDataList;
}
private void ValidateData()
{
List<RowData> rowDataList = (List<RowData>)ViewState["GridData"];
foreach (GridViewRow row in this.MyDataGrid.Rows)
{
if (row.RowType == System.Web.UI.WebControls.DataControlRowType.DataRow && row.Enabled)
ValidateDataRow(rowDataList, row);
}
}
private void ValidateDataRow(List<RowData> rowDataList, GridViewRow gridViewRow)
{
RowData rowData = rowDataList[gridViewRow.DataItemIndex];
bool valueOK = false;
var txtNewValue = gridViewRow.Cells[COL_NEW_VALUE].FindControl("txtNewValue") as TextBox;
var txtNewDate = gridViewRow.Cells[COL_NEW_DATE].FindControl("txtNewDate") as TextBox;
var labelError = gridViewRow.Cells[COL_NEW_VALUE].FindControl("lblError") as Label;
var labelInfo = gridViewRow.Cells[COL_NEW_VALUE].FindControl("lblStatus") as Label;
labelInfo.Text = string.Empty;
labelError.Text = string.Empty;
rowData.InfoText = string.Empty;
rowData.ErrorText = string.Empty;
rowData.EnteredDateCache = txtNewDate.Text;
rowData.EnteredValueCache = txtNewValue.Text;
if (rowData != null && (!string.IsNullOrEmpty(txtNewValue.Text) || !string.IsNullOrEmpty(txtNewDate.Text)))
{
if (!txtNewValue.Text.IsNumber())
{
rowData.ErrorText = rowData.Name + " must be a number.";
AddCustomValidatorForCell(rowData.ErrorText, gridViewRow, 4);
}
else
{
if (txtNewValue.Text != "100")
{
rowData.ErrorText = rowData.Name + " is invalid.";
AddCustomValidatorForCell(rowData.ErrorText, gridViewRow, 4);
}
else
{
valueOK = true;
}
}
}
}
private void AddCustomValidatorForCell(string errorMessage, GridViewRow gridViewRow, int cellIndex)
{
var labelError = gridViewRow.Cells[cellIndex].FindControl("lblError") as Label;
var divInfoError = gridViewRow.Cells[cellIndex].FindControl("ErrorPanel") as Panel;
labelError.Text = errorMessage;
labelError.ToolTip = errorMessage;
labelError.Attributes.Add("style", "color: red;");
CustomValidator validatePower = new CustomValidator()
{
IsValid = false,
ErrorMessage = errorMessage,
EnableViewState = false,
};
Page.Validators.Add(validatePower);
}
protected void SaveButton_Click(object sender, EventArgs e)
{
SaveData();
this.MyDataGrid.DataSource = ViewState["GridData"];
this.MyDataGrid.DataBind();
}
protected void MyDataGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == System.Web.UI.WebControls.DataControlRowType.DataRow)
{
var rowData = e.Row.DataItem as RowData;
if (rowData != null)
{
DataControlFieldCell txtNewDate = (DataControlFieldCell)e.Row.Cells[COL_NEW_DATE];
DataControlFieldCell txtNewValue = (DataControlFieldCell)e.Row.Cells[COL_NEW_VALUE];
e.Row.Cells[1].Text = rowData.Date.HasValue ? rowData.Date.ToString() : string.Empty;
e.Row.Cells[2].Text = rowData.Value.HasValue ? rowData.Value.Value.ToString() : string.Empty;
txtNewValue.Enabled = txtNewDate.Enabled = (canEdit & rowData.Editable);
if (!string.IsNullOrEmpty(rowData.EnteredDateCache))
txtNewDate.Text = rowData.EnteredDateCache;
if (!string.IsNullOrEmpty(rowData.EnteredValueCache))
txtNewValue.Text = rowData.EnteredValueCache;
(e.Row.FindControl("lblStatus") as Label).Text = rowData.InfoText;
(e.Row.FindControl("lblError") as Label).Text = rowData.ErrorText;
//(e.Row.FindControl("ErrorPanel") as Panel).Visible = (!string.IsNullOrEmpty(rowData.InfoText) || !string.IsNullOrEmpty(rowData.ErrorText));
}
}
}
[Serializable()]
private class RowData
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime? Date { get; set; }
public double? Value { get; set; }
public string ValidationRule { get; set; }
public string ErrorText { get; set; }
public string InfoText { get; set; }
public string EnteredDateCache { get; set; }
public string EnteredValueCache { get; set; }
public bool Editable { get; set; }
}
}
public static class StringExtensionMethods
{
public static bool IsNumber(this String str)
{
double Number;
if (double.TryParse(str, out Number)) return true;
return false;
}
}

Looks like I was incorrectly setting the controls incorrectly in the RowDataBound event. This should be:
if (e.Row.RowType == System.Web.UI.WebControls.DataControlRowType.DataRow)
{
var rowData = e.Row.DataItem as RowData;
if (rowData != null)
{
DataControlFieldCell txtNewDate = (DataControlFieldCell)e.Row.Cells[COL_NEW_DATE];
if (!string.IsNullOrEmpty(rowData.EnteredValueCache))
{
var txtNewValue = (e.Row.FindControl("txtNewValue") as TextBox);
txtNewValue.Enabled = txtNewDate.Enabled = (canEdit & rowData.Editable);
txtNewValue.Text = rowData.EnteredValueCache;
}
(e.Row.FindControl("lblStatus") as Label).Text = rowData.InfoText;
(e.Row.FindControl("lblError") as Label).Text = rowData.ErrorText;
}
}
Remove the following lines from SaveData:
(row.FindControl("lblStatus") as Label).Text = dataItem.InfoText;
(row.FindControl("lblError") as Label).Text = dataItem.ErrorText;
Remove the following from ValidateDataRow:
labelInfo.Text = string.Empty;
labelError.Text = string.Empty;
I am assuming that calling the following:
DataControlFieldCell txtNewValue = (DataControlFieldCell)e.Row.Cells[COL_NEW_VALUE];
if (!string.IsNullOrEmpty(rowData.EnteredValueCache))
txtNewValue.Text = rowData.EnteredValueCache;
Will remove the controls from the template column when the data is set (which would be on the invalid value as it is not cleared in the cache) which is why I saw the error when an invalid value was entered.

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>

ASP.NET - User control custom data binding

I develop user control Date of Birth, which contains 3 DropDownList.
I need to make data binding, but I dunno how.
public partial class DofControl : System.Web.UI.UserControl {
public const int YearsCount = 100;
int _year;
Months _month;
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack ) {
Bind();
}
if (SessionWrapper.JustInserted)
{
Bind();
SessionWrapper.JustInserted = false;
}
}
public object DataSource {
get; set;
}
private void Bind() {
int[] years = new int[YearsCount];
int from = DateTime.Now.Year - 5;
int to = from - 100;
for (int i = 0; i < YearsCount; i++) {
years[i] = to;
to++;
}
ddlYear.DataSource = years;
ddlYear.DataBind();
ddlMonth.DataSource = Enum.GetNames(typeof(Months));
ddlMonth.DataBind();
_year = Int32.Parse(ddlYear.SelectedValue);
_month = (Months)Enum.Parse(typeof(Months), ddlMonth.SelectedValue);
BindDays(_year, _month);
if (DataSource==null)
{
ddlYear.SelectedValue = years.Max().ToString();
ddlMonth.SelectedValue = Months.January.ToString();
ddlDay.SelectedValue = "1";
}
else
{
ddlYear.SelectedValue = Convert.ToDateTime(DataSource).Year.ToString();
ddlMonth.SelectedValue = Enum.GetName(typeof(Months), Convert.ToDateTime(DataSource).Month);
ddlDay.SelectedValue = Convert.ToDateTime(DataSource).Day.ToString();
}
}
enum Months { January = 1 //....... }
//Is this right?
[Bindable(true,BindingDirection.TwoWay)]
public DateTime Date {
private get {
return DateTime.Parse(string.Format("{0}/{1}/{2}", ddlDay.Text, ddlMonth.Text, ddlYear.Text));
}
set
{
ddlYear.SelectedValue = value.Year.ToString();
ddlMonth.SelectedValue = value.Month.ToString();
ddlDay.SelectedValue = value.Day.ToString();
}
}
protected void ddlMonth_SelectedIndexChanged(object sender, EventArgs e) {
_year = int.Parse(ddlYear.SelectedValue);
_month = (Months)Enum.Parse(typeof(Months), ddlMonth.SelectedValue);
BindDays(_year, _month);
}
protected void ddlYear_SelectedIndexChanged(object sender, EventArgs e) {
_year = int.Parse(ddlYear.SelectedValue);
_month = (Months)Enum.Parse(typeof(Months), ddlMonth.SelectedValue);
BindDays(_year, _month);
}
public bool IsLeapYear(int year) { //..... }
private void BindDays(int year, Months month) {
List<int> days = new List<int>();
switch (month) {
case Months.January:
case Months.March:
for (int i = 1; i <= 31; i++)
days.Add(i);
break;
case Months.February:
//does not matter
}
}
I use DofControl in a page Update.aspx inside asp:DetailsView.
<asp:ObjectDataSource ID="odsOneStudent" runat="server"
SelectMethod="GetStudentById"
..////
<asp:DetailsView
//......
<Fields>
<asp:BoundField DataField="SurName" HeaderText="SurName" />
<asp:TemplateField HeaderText="Dof">
<EditItemTemplate>
<uc:Dof runat="server" ID="dfDof" Date='<%#Eval("Dof") %>' />
</EditItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
I does not work, I get an error "ddlMonth' has a SelectedValue which is invalid because it does not exist in the list of items.
Parameter name: value"
Am I miss anything?
update: I get an error: "Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control"
When you set the SelectedValue of a DropDownList the value must be contained in the list's items.
Check where you are setting the SelectedValue that the value you are using is correct and contained in the DropDownList.Items

Implementing a pager for asp.net's DataList/Repeater

I have a DataList showing the results, and a Repeater that is supposed to be the pager.
I decided to use the page number by redirecting with a QueryString parameter, so it will also be bookmarkable ... My problem is mainly in the UI actually.
If I put DIV's with their onclick calling a JS function that does window.location = url + pagenumber , then somehow I have to deal with QueryString operations via JS which is a bit messy.
If I use LinkButton objects within the ItemTemplate, then the Redirecting happens only when the linkbutton is clicked while whole div has cursor: pointer , you know what I mean.
What would be the best approach to this? Thanks in advance.
Note: I really want to spend the time and effort implementing my own server-side paging.
I think its more fun than reading 3rd party manuals.
Markup:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="SoruListe.ascx.cs" Inherits="SoruListe" %>
<%# Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<%# Register src="EtiketControl.ascx" tagname="EtiketControl" tagprefix="uc1" %>
<script type="text/javascript">
$(document).ready(function() {
if ($('.pageritem')) {
$('#pageritem-' + get_pagenumber()).addClass("pagerselected");
}
});
function soruyuac(id) {
var url = "SoruDetay.aspx?sid=" + id;
window.location = url;
}
function get_QueryString(fieldname) {
var qstr = window.location.search.substring(1);
var pairs = qstr.split('&');
for (i = 0; i < pairs.length; i++) {
var keyval = pairs[i].split('=');
if (keyval[0] && keyval[0] == fieldname) {
return keyval[1];
}
}
}
function set_QueryString(fieldname, value) {
var rawurl = window.location.href;
if (rawurl.indexOf('?') > -1) { rawurl = window.location.href.split('?')[0]; }
var qstr = window.location.search.substring(1);
var pairs = qstr.split('&');
var foundit = false;
for (i = 0; i < pairs.length; i++) {
if (i == 0 && rawurl.indexOf('?') == -1) { rawurl += '?' }; ///Buraya kadar saglam görünüyo
var curpair = pairs[i].split('=');
if (curpair[0] == fieldname) { /// paramname'i al ama deger için yeni geleni koy
foundit = true;
rawurl += curpair[0] + '=' + value;
if (i != pairs.length - 1) { rawurl += '&' }
}
else { ///aynen geri doldur
rawurl += curpair[0] + '=' + curpair[1];
if (i != pairs.length - 1) { rawurl += '&' }
}
}
if (!foundit) { rawurl += '&' + fieldname + '=' + value; }
///
return rawurl;
}
function changepage(pagenum) {
window.location = set_QueryString('pg', pagenum);
}
function get_pagenumber() {
var pgn = get_QueryString('pg');
if (pgn == null) return 1;
return pgn;
}
function skipfrom(from) {
window.location = set_QueryString('skip', from);
}
</script>
<div id="dvPager">
<asp:Repeater ID="pagerSorular" runat="server">
<ItemTemplate>
<div class="pageritem pagertext" id='<%# "pageritem-" + Container.DataItem %>'
onclick='<%# (Container.DataItem != "...")?("changepage(" + Container.DataItem + ");"): ("skipfrom(" + (this.PageNumber + 4) + ");") %>' >
<%# Container.DataItem %>
</div>
</ItemTemplate>
</asp:Repeater>
</div>
<asp:DataList ID="gridSorular" runat="server" Width="100%" OnItemDataBound="gridSorular_ItemDataBound">
<ItemTemplate>
<div class="soruwrapper">
<asp:HiddenField ID="hfSoruID" runat="server" Value='<%# Eval("ID") %>' />
<div class="viewsbox boxtext">
<b class="boxtext"><%# Eval("VIEWS") %></b>
<br />Okuyan
<hr />
<div class='<%# "answersbox boxtext " + ((int.Parse(Eval("ANSWERS").ToString()) > 0) ? "isanswered" : "notanswered") %>'>
<b class="numtext"><%# Eval("ANSWERS")%></b>
<br />Cevap
</div>
</div>
<div class="item" onclick='<%# "soruyuac(" + Eval("ID") + ");" %>'>
<div class="soruheader" title='<%# Server.HtmlEncode(Eval("BODY").ToString())%>' >
<%# Eval("TITLE") %>
</div>
<div class="etiketwrapper">
<uc1:EtiketControl ID="EtiketControl1" runat="server" />
</div>
</div>
</div>
</ItemTemplate>
</asp:DataList>
Server-Side:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DataLayer;
public partial class SoruListe : System.Web.UI.UserControl
{
public int PageNumber
{
get
{
string strPgNum = Request.QueryString["pg"] as String;
if (!String.IsNullOrEmpty(strPgNum))
{
int pgnum;
if (int.TryParse(strPgNum, out pgnum))
{
if (pgnum <= 0)
{
return pgnum;
}
else
{
return 1;
}
}
else
{
return 1;
}
}
else
{
return 1;
}
}
}
public int PageSize { get { return 1; } }
public string PageName {
get
{
string url = Request.Url.ToString();
string[] parts = url.Split(new char[]{'/'});
return parts[parts.Length - 1];
}
}
public void Page_Load(object sender, EventArgs e)
{
}
public void SonSorular()
{
gridSorular.DataSource = BLL.SonSorular(300,300);
gridSorular.DataBind();
///
}
protected void CreatePager()
{
int pagenumber = this.PageNumber;
int start = 1;
if (PageNumber > 3)
{
start = pagenumber - 3;
}
int finish = pagenumber + 3;
int sorucount;
using (DataAccessDataContext db = new DataAccessDataContext())
{
sorucount = db.Sorus.Count();
}
List<string> pageritemlist = new List<string>();
int c = start;
for (int i = 0; i < finish; i++)
{
pageritemlist.Add((c++).ToString());
}
pageritemlist.Add("...");
pageritemlist.Add(sorucount.ToString());
pagerSorular.DataSource = pageritemlist.ToArray();
pagerSorular.DataBind();
}
public void ListAll()
{
CreatePager();
int pagesize = this.PageSize;
int skip = this.PageNumber * pagesize;
ListSorular(skip, pagesize);
}
public void Popular()
{
}
public void Active()
{
}
public void Unanswered()
{
}
public void ListSorular(int skip, int take)
{
using (DataAccessDataContext db = new DataAccessDataContext())
{
List<SoruGridView> sorular = (from s in db.Sorus
select new SoruGridView() {
ID = s.ID, TITLE = s.TITLE, BODY = s.BODY, TARIH = s.DATECREATED, VIEWS = s.VIEWS, ANSWERS = s.Cevaps.Count
}).Skip(skip).Take(take).ToList();
gridSorular.DataSource = sorular;
gridSorular.DataBind();
}
}
protected void gridSorular_ItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem )
{
HiddenField hfsoruid = e.Item.FindControl("hfSoruID") as HiddenField;
if (hfsoruid != null)
{
int sid;
if (int.TryParse(hfsoruid.Value, out sid))
{
EtiketControl tagsctrl = (EtiketControl)e.Item.FindControl("EtiketControl1");
tagsctrl.GetTags(sid);
}
}
}
}
}
There is also my JavaScript querystring parser written by me :)

Extending a (ASP.NET) BoundField

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");
}
}
}

Object and nested datalists

I am having trouble displaying my object in a datalist.
My object loks like this:
public class Course
{
private string courseName;
private DateTime[] courseDates;
public string CourseName
{
get { return courseName; }
set { courseName = value; }
}
public DateTime[] CourseDates
{
get { return courseDates; }
set {
foreach (DateTime dt in courseDates)
{
if (dt < DateTime.Now)
throw new Exception("The date of the course has to be after todays date.");
}
courseDates = value; }
}
public Course(string _courseName, DateTime[] _courseDates)
{
courseName = _courseName;
courseDates = _courseDates;
}
}
When I try to display it in a datalist the name of the course looks ok. But The dates are not shown.
So I was thinking I needed a nested datalist but then I don't know how to fill the second datalist with the dates in the object.
I've show two solutions:
<asp:DataList ID="DataList1" runat="server"
onitemdatabound="DataList1_ItemDataBound">
<ItemTemplate>
<td><%# DataBinder.Eval(Container.DataItem, "CourseName")%></td>
<td><%# RenderDates( DataBinder.Eval(Container.DataItem, "CourseDates"))%></td>
<td>
<asp:DataList ID="DateList" runat="server">
<ItemTemplate>
<td><%# Container.DataItem%></td>
</ItemTemplate>
</asp:DataList>
</td>
</ItemTemplate>
</asp:DataList>
and
public string RenderDates(object dates)
{
DateTime[] ds = dates as DateTime[];
StringBuilder sb = new StringBuilder();
if( ds != null && ds.Length > 0)
{
sb.Append(ds[0]);
for (int i = 1; i < ds.Length; i++)
{
sb.AppendFormat(" - {0}", ds[i]);
}
}
return sb.ToString();
}
protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)
{
DataListItem item = e.Item;
if ((item.ItemType == ListItemType.Item) ||
(item.ItemType == ListItemType.AlternatingItem))
{
var innerList= (DataList)item.FindControl("DateList");
innerList.DataSource = ((Course) item.DataItem).CourseDates;
innerList.DataBind();
}
}

Resources