I'm struggling a lot and I hope someone can help me please.
I have a 4 dropdownlists, a search button and a normal gridview with a basic SQLdataConnection.
The SQLdataConnection is a stored procedure that retrieves 3 tables based on 4 parameters. These 3 tables are then joined together into the gridview.
BUT
One of the dropdownlists has the options of Total, Fast and Slow. So based on which option the user chooses the respective table should be loaded into the gridview when the search button is pressed. (So if total is chosen, the total table should be loaded into the gridview)
I don't know if the SQLdataConnection should be changed with each option to show only the appropriate table.
Below is a copy of the html of the dropdowns and gridview as well as the code behind.
<tr>
<td style="text-align: right" class="pad-right-0">
<asp:DropDownList ID="selSeconds" runat="server" CssClass="selectbox select-chr" Visible="true"></asp:DropDownList>
<asp:DropDownList ID="selHours" runat="server" CssClass="selectbox select-chr" Visible="true"></asp:DropDownList>
<asp:DropDownList ID="selMerchantId" runat="server" CssClass="selectbox select-chr" Visible="true"></asp:DropDownList>
<asp:DropDownList ID="selTableType" runat="server" CssClass="selectbox select-chr" Visible="true"></asp:DropDownList>
<asp:Button ID="btnSearch" runat="server" CssClass="btn btn-primary btn-danger tip-s medium grey" ValidationGroup="Search" OnClick="btnSearch_Click" Text="<%$Resources:Resource, btnSearch %>" />
<asp:ImageButton ID="btnExportToExcel" runat="server" CssClass="btn btn-primary btn-danger tip-s medium grey" ValidationGroup="Search" onclick="btnExportToExcel_Click" Text="Export to excel" ImageUrl="images/Excel.png" AlternateText="<%$Resources:Resource, lblExportExcel %>"
CausesValidation="false" />
<asp:RequiredFieldValidator ID="rqrdMerchantId" runat="server" ErrorMessage="<%$Resources:Resource, lblRequired %>" ControlToValidate="selMerchantId" ForeColor="Red" />
</td>
</tr>
</table>
<asp:HiddenField ID="hdnMerchantId" runat="server" Value="0" />
<asp:GridView ID="gridSpeedAnalysis" runat="server" DataSourceID="gridSqlConnection">
</asp:GridView>
<asp:SqlDataSource ID="gridSqlConnection" runat="server"></asp:SqlDataSource>
protected void Page_Load(object sender, EventArgs e)
{
if (Session["UserName"] == null || Session["UserType"] == null)
{
Response.Redirect("Login.aspx");
}
LoadDropDowns();
}
private void LoadDropDowns()
{
System.Web.UI.WebControls.ListItem item;
selSeconds.Items.Insert(0, new System.Web.UI.WebControls.ListItem("Select Second", "0"));
int index = 1;
for (int Second = 0; Second <= 10; Second++)
{
System.Web.UI.WebControls.ListItem li = new System.Web.UI.WebControls.ListItem(Second.ToString(), Second.ToString());
selSeconds.Items.Insert(index, li);
index++;
}
item = selSeconds.Items.FindByValue(DateTime.Now.Year.ToString());
selSeconds.SelectedIndex = selSeconds.Items.IndexOf(item);
if (Session["UserType"] != null && (Session["UserType"].ToString().ToLower() == "System Administrator".ToLower()))
{
selMerchantId.DataSource = BOL.MerchantGroup.Load();
selMerchantId.DataTextField = "Description";
selMerchantId.DataValueField = "MerchantId";
selMerchantId.DataBind();
selMerchantId.Items.Insert(0, new System.Web.UI.WebControls.ListItem { Value = "0", Text = "Select Group" });
rqrdMerchantId.InitialValue = "0";
}
else if (Session["UserType"].ToString().ToLower() == "Head Office".ToLower())
{
BOL.MerchantGroup group = new BOL.MerchantGroup(int.Parse(hdnMerchantId.Value));
selMerchantId.Items.Insert(0, new System.Web.UI.WebControls.ListItem { Value = hdnMerchantId.Value, Text = group.Description });
}
DataTable dt = BOL.Merchant.GetDropdownByMerhcantGroupId(int.Parse(Session["MerchantGroupId"].ToString()));
selMerchantId.DataSource = dt;
selMerchantId.DataTextField = "Name";
selMerchantId.DataValueField = "MerchantId";
selMerchantId.DataBind();
selTableType.Items.Insert(0, new System.Web.UI.WebControls.ListItem {Text = "Total"});
selTableType.Items.Insert(0, new System.Web.UI.WebControls.ListItem {Text = "Fast" });
selTableType.Items.Insert(0, new System.Web.UI.WebControls.ListItem {Text = "Slow" });
}
protected void btnSearch_Click(object sender, EventArgs e)
{
}
I have what may be a rather complicated issue. I have an extended gridview control that I swear used to work all the time, but I went away for a while, came back, and it doesn't work anymore (I'm the sole programmer).
The extended gridview is designed so that it always shows a footer row (for inserting new rows). It loads and displays existing data correctly. If there are no rows, then adding the data works fine. But if I'm adding a new row to a gridview that already has existing rows, I get an issue where gvPhones.FooterRow is null, so it can't find the control I'm referencing.
Here's the extended gridview class (gotten from a stackoverflow page):
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
//https://stackoverflow.com/questions/994895/always-show-footertemplate-even-no-data/10891744#10891744
namespace WebForms.LocalCodeLibrary.Controls
{
//modified from https://stackoverflow.com/questions/3437581/show-gridview-footer-on-empty-grid
public class GridViewExtended : GridView
{
private GridViewRow _footerRow;
[DefaultValue(false), Category("Appearance"), Description("Include the footer when the table is empty")]
public bool ShowFooterWhenEmpty { get; set; }
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(false)]
public override GridViewRow FooterRow
{
get
{
if ((this._footerRow == null))
{
this.EnsureChildControls();
}
return this._footerRow;
}
}
protected override int CreateChildControls(System.Collections.IEnumerable dataSource, bool dataBinding)
{
//creates all the rows that would normally be created when instantiating the grid
int returnVal = base.CreateChildControls(dataSource, dataBinding);
//if no rows were created (i.e. returnVal == 0), and we need to show the footer row, then we need to create and bind the footer row.
if (returnVal == 0 && this.ShowFooterWhenEmpty)
{
Table table = this.Controls.OfType<Table>().First<Table>();
DataControlField[] dcf = new DataControlField[this.Columns.Count];
this.Columns.CopyTo(dcf, 0);
//creates the footer row
this._footerRow = this.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal, dataBinding, null, dcf, table.Rows, null);
if (!this.ShowFooter)
{
_footerRow.Visible = false;
}
}
return returnVal;
}
private GridViewRow CreateRow(int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState, bool dataBind, object dataItem, DataControlField[] fields, TableRowCollection rows, PagedDataSource pagedDataSource)
{
GridViewRow row = this.CreateRow(rowIndex, dataSourceIndex, rowType, rowState);
GridViewRowEventArgs e = new GridViewRowEventArgs(row);
if ((rowType != DataControlRowType.Pager))
{
this.InitializeRow(row, fields);
}
else
{
this.InitializePager(row, fields.Length, pagedDataSource);
}
//if the row has data, sets the data item
if (dataBind)
{
row.DataItem = dataItem;
}
//Raises the RowCreated event
this.OnRowCreated(e);
//adds the row to the gridview's row collection
rows.Add(row);
//explicitly binds the data item to the row, including the footer row and raises the RowDataBound event.
if (dataBind)
{
row.DataBind();
this.OnRowDataBound(e);
row.DataItem = null;
}
return row;
}
}
}
Here's the relevant stuff in the ASPX page:
<%# Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="ContactEdit.aspx.cs" Inherits="WebForms.Directory.ContactEdit" %>
<%# Register TagPrefix="gcctl" Namespace="WebForms.LocalCodeLibrary.Controls" Assembly="WebForms" %>
<asp:Content ID="Content1" ContentPlaceHolderID="Head" runat="server">
<style>
</style>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<div id="bodycontent" class="body-content">
<h2><asp:Literal ID="formheader" runat="server" /></h2>
<!-- Start: Main Customer section -->
<asp:Panel ID="mainformcontent" runat="server" CssClass="formsection">
<section id="mainform" class="simplelayoutform">
<asp:TextBox id="customerid" type="hidden" runat="server" />
<asp:TextBox id="contactid" type="hidden" runat="server" />
</section>
</asp:Panel>
<!-- End: Main Customer section -->
<!-- Start: Phones section -->
<asp:SqlDataSource ID="gvPhonesDataSource" runat="server" OnInserted="gvPhonesDataSource_Inserted"
ConnectionString="<%$ ConnectionStrings:ConnString %>"
SelectCommand="SELECT p.[CustomerPhoneID]
,p.[CustomerID]
,LTRIM(COALESCE(cc.FirstName,'') + ' ' + COALESCE(cc.LastName,'')) AS ContactFullName
,p.CustomerContactID
,p.PhoneTypeID
,lp.PhoneType
,p.[PhoneNumber]
,p.[Extension]
,p.[FormattedPhone]
,p.[IsActive]
,CASE WHEN p.LocationID IS NULL THEN CASE WHEN p.CustomerContactID IS NULL THEN 0 ELSE 1 END ELSE 2 END AS SortOrder
FROM [dbo].[Phones] p
LEFT JOIN dbo.Contacts cc ON p.CustomerContactID = cc.CustomerContactID
LEFT JOIN list.PhoneTypes lp ON p.PhoneTypeID = lp.PhoneTypeID
WHERE p.CustomerContactID = #CustomerContactID"
DeleteCommand="DELETE FROM [dbo].[Phones] WHERE [CustomerPhoneID] = #CustomerPhoneID"
InsertCommand="INSERT INTO [dbo].[Phones] ([CustomerID]
, [CustomerContactID]
, [PhoneNumber]
, [Extension]
, [PhoneTypeID]
, LastModifiedByStaffID)
VALUES (#CustomerID
, #CustomerContactID
, CASE WHEN COALESCE(#FormattedPhone, '')='' THEN NULL ELSE LTRIM(RTRIM(LEFT(dbo.RemoveNonNumeric(#FormattedPhone),10))) END
, CASE WHEN COALESCE(#FormattedPhone, '')='' THEN NULL ELSE CASE WHEN LTRIM(RTRIM(SUBSTRING(dbo.RemoveNonNumeric(#FormattedPhone),11,1000))) = '' THEN NULL ELSE LTRIM(RTRIM(SUBSTRING(dbo.RemoveNonNumeric(#FormattedPhone),11,1000))) END END
, #PhoneTypeID
, #StaffID)"
UpdateCommand="UPDATE [dbo].[CustomerPhones]
SET [CustomerContactID] = #CustomerContactID
, [PhoneNumber] = CASE WHEN COALESCE(#FormattedPhone, '')='' THEN NULL ELSE LTRIM(RTRIM(LEFT(dbo.RemoveNonNumeric(#FormattedPhone),10))) END
, [Extension] = CASE WHEN COALESCE(#FormattedPhone, '')='' THEN NULL ELSE CASE WHEN LTRIM(RTRIM(SUBSTRING(dbo.RemoveNonNumeric(#FormattedPhone),11,1000))) = '' THEN NULL ELSE LTRIM(RTRIM(SUBSTRING(dbo.RemoveNonNumeric(#FormattedPhone),11,1000))) END END
, [PhoneTypeID] = #PhoneTypeID
, [IsActive] = #IsActive
, [DateModified] = getdate()
, [LastModifiedByStaffID] = #StaffID
WHERE [CustomerPhoneID] = #CustomerPhoneID">
<SelectParameters>
<asp:ControlParameter Name="CustomerContactID" Type="Int32" ControlID="contactid" PropertyName="Text" />
</SelectParameters>
<DeleteParameters>
<asp:Parameter Name="CustomerPhoneID" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:ControlParameter Name="CustomerContactID" Type="Int32" ControlID="contactid" PropertyName="Text" />
<asp:Parameter Name="FormattedPhone" Type="String" />
<asp:Parameter Name="PhoneTypeID" Type="Int32" />
<asp:Parameter Name="IsActive" Type="Boolean" />
<asp:SessionParameter Name="StaffID" Type="Int32" SessionField="StaffID" />
<asp:Parameter Name="CustomerPhoneID" Type="Int32" />
</UpdateParameters>
<InsertParameters>
<asp:ControlParameter Name="CustomerID" Type="Int32" ControlID="customerid" PropertyName="Text" />
<asp:ControlParameter Name="CustomerContactID" Type="Int32" ControlID="contactid" PropertyName="Text" />
<asp:Parameter Name="PhoneTypeID" Type="Int32" />
<asp:Parameter Name="FormattedPhone" Type="String" />
<asp:SessionParameter Name="StaffID" Type="Int32" SessionField="StaffID" />
</InsertParameters>
</asp:SqlDataSource>
<asp:Panel ID="phonesformcontent" runat="server" CssClass="formsection separate">
<section id="phonesform" class="simplelayoutform">
<h3>All Phones</h3>
<gcctl:MyCheckBox ID="chkPhoneShowInactive" Text="Show Inactive?" Checked="false" AutoPostBack="true" OnCheckedChanged="chkPhoneShowInactive_CheckedChanged" runat="server" />
<asp:label id="lblPhoneMessage" CssClass="responsemsg" runat="server" enableviewstate="False" />
<gcctl:gridviewextended ID="gvPhones" runat="server" DataSourceID="gvPhonesDataSource"
AutoGenerateColumns="False" DataKeyNames="CustomerPhoneID" EmptyDataText="No phones on record."
CssClass="searchresultsgrid" ShowFooter="True" OnRowCommand="gvPhones_RowCommand" AllowSorting="True"
ShowFooterWhenEmpty="true" OnRowDataBound="gvPhones_RowDataBound">
<Columns>
<asp:BoundField DataField="CustomerPhoneID" InsertVisible="false" ReadOnly="true" Visible="False" />
<asp:TemplateField HeaderText="Phone Type" SortExpression="PhoneType">
<FooterTemplate>
<asp:DropDownList ID="cboPhoneTypeID" runat="server"
DataSourceID="DataSourcePhoneTypes" DataTextField="PhoneType" DataValueField="PhoneTypeID"
SelectedValue='<%# Bind("PhoneTypeID") %>'>
</asp:DropDownList>
</FooterTemplate>
<EditItemTemplate>
<asp:DropDownList ID="cboPhoneTypeID" runat="server"
DataSourceID="DataSourcePhoneTypes" DataTextField="PhoneType" DataValueField="PhoneTypeID"
SelectedValue='<%# Bind("PhoneTypeID") %>'>
</asp:DropDownList>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblPhoneTypeID" runat="server" Text='<%# Bind("PhoneType") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Phone" SortExpression="PhoneNumber">
<FooterTemplate>
<asp:TextBox runat="server" Text='<%# Bind("FormattedPhone") %>' ID="txtPhone"></asp:TextBox>
</FooterTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" Text='<%# Bind("FormattedPhone") %>' ID="txtPhone"></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label runat="server" Text='<%# Bind("FormattedPhone") %>' ID="lblPhone"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Active?" SortExpression="IsActive">
<FooterTemplate>
<asp:CheckBox runat="server" Checked='<%# Bind("IsActive") %>' ID="chkPhoneIsActive"></asp:CheckBox>
</FooterTemplate>
<EditItemTemplate>
<asp:CheckBox runat="server" Checked='<%# Bind("IsActive") %>' ID="chkPhoneIsActive"></asp:CheckBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label runat="server" Text='<%# Bind("IsActive") %>' ID="lblPhoneIsActive"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
<EditItemTemplate>
<asp:LinkButton runat="server" Text="Update" CommandName="Update" CausesValidation="True" ID="PhoneUpdate"></asp:LinkButton> <asp:LinkButton runat="server" Text="Cancel" CommandName="Cancel" CausesValidation="False" ID="PhoneEditCancel"></asp:LinkButton>
</EditItemTemplate>
<ItemTemplate>
<asp:LinkButton runat="server" Text="Edit" CommandName="Edit" CausesValidation="False" ID="PhoneEdit"></asp:LinkButton> <asp:LinkButton runat="server" Text="Delete" CommandName="Delete" CausesValidation="False" ID="PhoneDelete"></asp:LinkButton>
</ItemTemplate>
<FooterTemplate>
<asp:LinkButton runat="server" Text="Save New Phone" CommandName="FooterInsert" CausesValidation="True" ID="PhoneInsert"></asp:LinkButton>
</FooterTemplate>
</asp:TemplateField>
</Columns>
</gcctl:gridviewextended>
<div id="phonenotes" class="tip">
<div>NUMBERS ONLY - NO LETTER CODES IN THE PHONE FIELD!</div>
<div>Be sure to always enter the area code, especially if you're also adding an extension.</div>
<div>Note that only numbers will stay in the "Phone" field. Anything else you enter will disappear once it goes behind the scenes. The first 10 digits will become the phone number, and any remaining digits will become the extension.</div>
</div>
</section>
</asp:Panel>
<!-- End: Phones section -->
<div id="responsetextdiv" class="error"><asp:Literal ID="responsetext" runat="server"></asp:Literal></div>
</div>
<asp:XmlDataSource ID="DataSourcePhoneTypes" runat="server" DataFile="~/XML/PhoneTypes.xml" EnableCaching="true">
</asp:XmlDataSource>
</asp:Content>
Here's the code where I get the error:
protected void gvPhones_RowCommand(object sender, GridViewCommandEventArgs e)
{
// Insert data if the CommandName == "Insert"
// and the validation controls indicate valid data...
if (e.CommandName == "FooterInsert" && Page.IsValid)
{
//ERROR HAPPENS ON THE FOLLOWING LINE:
DropDownList PhoneTypeID = (DropDownList)gvPhones.FooterRow.FindControl("cboPhoneTypeID");
TextBox FormattedPhone = (TextBox)gvPhones.FooterRow.FindControl("txtPhone");
gvPhonesDataSource.InsertParameters["PhoneTypeID"].DefaultValue = PhoneTypeID.SelectedValue.ToString();
string sFormattedPhone = null;
if (!string.IsNullOrEmpty(FormattedPhone.Text))
sFormattedPhone = FormattedPhone.Text;
gvPhonesDataSource.InsertParameters["FormattedPhone"].DefaultValue = sFormattedPhone;
gvPhonesDataSource.InsertParameters["CustomerID"].DefaultValue = customerid.Text.ToString();
gvPhonesDataSource.InsertParameters["CustomerContactID"].DefaultValue = contactid.Text.ToString();
gvPhonesDataSource.InsertParameters["StaffID"].DefaultValue = System.Web.HttpContext.Current.Session["StaffID"].ToString();
// Insert new record
gvPhonesDataSource.Insert();
}
}
The full error I get is:
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 276: if (e.CommandName == "FooterInsert" && Page.IsValid)
Line 277: {
Line 278: DropDownList PhoneTypeID = (DropDownList)gvPhones.FooterRow.FindControl("cboPhoneTypeID");
Line 279: TextBox FormattedPhone = (TextBox)gvPhones.FooterRow.FindControl("txtPhone");
Line 280:
Source File: <snip> Line: 278
Stack Trace:
[NullReferenceException: Object reference not set to an instance of an object.]
GCWebForms.Directory.ContactEdit.gvPhones_RowCommand(Object sender, GridViewCommandEventArgs e) in <snip>ContactEdit.aspx.cs:278
System.Web.UI.WebControls.GridView.OnRowCommand(GridViewCommandEventArgs e) +137
System.Web.UI.WebControls.GridView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup) +95
System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +49
System.Web.UI.WebControls.GridViewRow.OnBubbleEvent(Object source, EventArgs e) +146
System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +49
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5450
When stepping through (when trying to add a new row to a gridview that already has data in it), I found that gvPhones.FooterRow says that it's null. Again, this only happens if there is data in gvPhones. If the datatable is empty, then the footerrow insert code works without a hitch.
Any help would be greatly appreciated! :-)
EDIT: adding the relevant code behind Page_Load. I just added the DataBind() statement, but it didn't make a difference.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
bool bolNewRec = (this.iContactID == null);
phonesformcontent.Visible = (!bolNewRec);
if (bolNewRec)
{ //snipping unrelated code
}
else
{
//snipping code that loads the data into the page
gvPhones.Sort("SortOrder, PhoneType", SortDirection.Ascending);
}
}
if (phonesformcontent.Visible)
gvPhones.DataBind();
}
...and, just in case, here's RowDataBound:
protected void gvPhones_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView rowView = (DataRowView)e.Row.DataItem;
bool bolShowInactive = chkPhoneShowInactive.Checked;
if (!bolShowInactive && (Convert.ToBoolean(rowView["IsActive"]) == false))
e.Row.Visible = false;
else
e.Row.Visible = true;
rowView = null;
}
if (e.Row.RowType == DataControlRowType.Footer)
{
CheckBox chkIsActive = (CheckBox)e.Row.FindControl("chkPhoneIsActive");
chkIsActive.Checked = true;
chkIsActive = null;
}
}
Try using the sender in your code as below:
Replace this line:
DropDownList PhoneTypeID = (DropDownList)gvPhones.FooterRow.FindControl("cboPhoneTypeID");
For this:
DropDownList PhoneTypeID = (DropDownList)((GridView)sender).FooterRow.FindControl("cboPhoneTypeID");
Also, check the page load if the problem is not with the postback.
My answer is based on this question:
Unable to get gridview footer values in RowCommand
UPDATE:
Change your GridViewExtended class,
ShowFooterWhenEmpty property:
[Category("Behavior")]
[Themeable(true)]
[Bindable(BindableSupport.No)]
public bool ShowFooterWhenEmpty
{
get
{
if (this.ViewState["ShowFooterWhenEmpty"] == null)
{
this.ViewState["ShowFooterWhenEmpty"] = false;
}
return (bool)this.ViewState["ShowFooterWhenEmpty"];
}
set
{
this.ViewState["ShowFooterWhenEmpty"] = value;
}
}
GridViewRow:
private GridViewRow _footerRow;
public override GridViewRow FooterRow
{
get
{
GridViewRow f = base.FooterRow;
if (f != null)
return f;
else
return _footerRow;
}
}
I based my changes on this link:
Always show FooterTemplate, even no data
I wound up scrapping this entire class. Instead, I made regular asp:gridviews that are based on datasources that have union selects with one row with -1 in the key column (since all of my tables have single autoincrement PKs, no row will legitimately have -1 in the key column), and then put the following in RowDataBound:
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView rowView = (DataRowView)e.Row.DataItem;
string sKeyName = gvPhones.DataKeyNames[0].ToString();
if ((rowView[sKeyName].ToString() == "-1"))
e.Row.Visible = false;
else
e.Row.Visible = true;
rowView = null;
}
This hides any row with -1 in the key column. So there's always at least one row in the gridview (even if that one row is hidden), and the footer row always shows.
I use a session to save the hashtable. It has different key-value pairs in it and some of the keys refer to 'List' object.
I have different buttons in the repeater control to change the value of the List and then put it back to hashtable. Then use the same session to save that hashtable. But sometimes the change made get lost in the session. Don't know why. I tried on my test server. It can work fine. While on Prod server, I met this problem.
Any suggestions?
<asp:Repeater ID="rptCountry" runat="server" OnItemDataBound="rptCountry_ItemDataBound" OnItemCommand="rptCountry_ItemCommand">
<ItemTemplate>
<asp:Button ID="btnCountry" runat="server" Text='<%#DataBinder.Eval(Container.DataItem, "Country").ToString() %>' CssClass="iButton Disabled" Enabled="false" UseSubmitBehavior="False" CommandName="Select" />
<asp:Label ID="hdnCountryCode" runat="server" Text='<%#DataBinder.Eval(Container.DataItem, "CountryCode")%>' Visible="false" />
</ItemTemplate>
</asp:Repeater>
protected void rptCountry_ItemCommand(object sender, RepeaterCommandEventArgs e)
{
if (e.CommandName.Equals("Select"))
{
Button btnCountry = (Button)e.Item.FindControl("btnCountry");
Label hdnCountryCode = (Label)e.Item.FindControl("hdnCountryCode");
if (Session["SearchFilter"] != null)
{
Hashtable htSearchFilter = (Hashtable)Session["SearchFilter"];
List<string> countries = (List<string>)htSearchFilter["Country"];
if (countries != null && countries.Count > 0)
{
bool countriesExists = false;
foreach (string country in countries)
{
if (country.Equals(hdnCountryCode.Text.Trim()))
{
countriesExists = true;
}
}
if (!countriesExists)
{
countries.Add(hdnCountryCode.Text.Trim());
btnCountry.CssClass = "iButton Active";
}
else
{
countries.Remove(hdnCountryCode.Text.Trim());
btnCountry.CssClass = "iButton";
}
}
else
{
countries.Add(hdnCountryCode.Text.Trim());
btnCountry.CssClass = "iButton Active";
}
htSearchFilter["Country"] = countries;
Session["SearchFilter"] = htSearchFilter;
ProvinceReloadControl(countries);
}
}
InitControl();
}
I am trying to find the formview inside my listview on the page load. However, my result is always null. I called the DataBind method first but still nothing.
Code Behind
protected void Page_Load(object sender, EventArgs e)
{
String list = itemdropdownlist.SelectedValue;
switch (list)
{
case "Section Item":
SectionListView.DataBind();
//SectionListView.Enabled = false;
var temp = (FormView)SectionListView.FindControl("SectionFormView");
temp.Enabled = true;
renderView(SectionListView, "hidden"); // hide listview on page load
break;
}
}
ASP.net code
<InsertItemTemplate>
<tr style="">
<td>
<div style="font-size: .8em;">
<asp:FormView ID="SectionFormView" runat="server" DataKeyNames="SectionItemID" DataSourceID="SectionDataSource">
<ItemTemplate>
<asp:Button ID="InsertButton" runat="server" Text="Insert" OnClick="SectionItemButton_Click" Font-Size="1.2em" />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel" Text="Clear" Font-Size="1.2em" />
<asp:Label ID="SectionItemLabel" runat="server" Text="SectionItem" Font-Bold="true" Font-Size="1.2em" />
<asp:TextBox ID="SectionItemTextBox" runat="server" />
<asp:Label ID="SectionItemSubLabel" runat="server" Text="SectionItem Label" Font-Bold="true" Font-Size="1.2em" />
<asp:TextBox ID="SectionItemLabelTextBox" runat="server" />
</ItemTemplate>
</asp:FormView>
</div>
</td>
</tr>
</InsertItemTemplate>
<ItemTemplate>
You got that error, because the listview was not binded yet, so i think the best way would be to do all this on the ItemDataBound event. You would find the FormView like:
if (e.Item.ItemType == ListViewItemType.DataItem)
{
FormView SFormView= (FormView)e.Item.FindControl("SectionFormView");
if (SFormView!= null)
{
//code here
}
}
You could use this code to find about anything. I used it before to find Literals that I created in code behind. Use this code to find your FormView
private readonly List<FormView> _foundControls = new List<FormView>();
public IEnumerable<FormView> FoundControls
{
get { return _foundControls; }
}
public void FindChildControlsRecursive(Control control)
{
foreach (Control childControl in control.Controls)
{
if (childControl.GetType() == typeof(FormView))
{
_foundControls.Add((FormView)childControl);
}
else
{
FindChildControlsRecursive(childControl);
}
}
}
FindChildControlsRecursive(<Insert relevent Code Here: Whatever element you want to search inside of like your listView, find that using FindControl>);
FormView[] strControl = new FormView[200];
strControl = FoundControls.ToArray();
foreach (FormView i in strControl)
{
if (i.ID.Equals("< insert controlId of your FormView>"))
{
// do something when you find it
}
}
From a listview control, when checkboxes are checked and a button is clicked from outside the listview, I need to be able to delete the items that have been checked. Here's the listview:
EDIT
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack) return;
var notes = (from n in db.Notes
select n).OrderBy(n => n.FiscalYear).ThenBy(n => n.Period);
notesListView.DataSource = notes;
notesListView.DataBind();
}
<asp:ListView ID="notesListView" ItemPlaceholderID="itemPlaceholder" runat="server">
<LayoutTemplate>
<div>
<asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
</div>
</LayoutTemplate>
<ItemTemplate>
<asp:CheckBox ID="checkNote" runat="server" />
<div><%# Eval("Period") %></div>
<div><%# Eval("FiscalYear") %></div>
<div><%# Eval("Account") %></div>
<div class="wrap"><%# Eval("Description") %></div>
</ItemTemplate>
<EmptyDataTemplate>
<div>No notes have been submitted.</div>
</EmptyDataTemplate>
</asp:ListView>
<br />
<asp:Button ID="deleteNotes" CssClass="deleteButton" Text="Delete Notes" runat="server" OnClick="deleteNotes_Click" />
Here's the code behind:
protected void deleteNotes_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in notesListView.Items)
{
// I know this is wrong, just not sure what to do
if (notesListView.SelectedIndex >= 0)
{
CheckBox ck = (CheckBox)item.FindControl("checkNote");
if (ck.Checked)
{
var index = item.DataItemIndex; // the item row selected by the checkbox
// db is the datacontext
db.Notes.DeleteOnSubmit(index);
db.SubmitChanges();
}
}
else
{
errorMessage.Text = "* Error: Nothing was deleted.";
}
}
}
You need to find the object before deleting it. To do so, I would add a hiddenfield to store NoteID like this:
<asp:HiddenField ID="hdnId" Value='<%#Eval("Id")%>' runat="server" />
<asp:CheckBox ID="checkNote" runat="server" />
... ... ...
And in my code I am finding the note by ID and deleting that note (You may use any other unique field instead of ID). My code may look like this:
... ... ...
int id = 0;
var hdnId = item.FindControl("hdnId") as HiddenField;
CheckBox ck = (CheckBox)item.FindControl("checkNote");
//I would check null for ck
if (ck != null && ck.Checked && hdnId != null && int.TryParse(hdnId.Value, out id)
{
// db is the datacontext
Note note = db.Notes.Single( c => c.Id== id );
db.Notes.DeleteOnSubmit(note );
db.SubmitChanges();
}