How to call ascx delegate to some other ascx btn click? - asp.net

I have ascx suppose A.ascx in which i am writing a delegate on OnInit() like this
btnUpdate.Click += delegate
{
if (MaxLength.HasValue && txtText.Text.Length >= MaxLength.Value)
{
lblError.Text = string.Format(Resources.ErrorMessage_FieldLength, MaxLength);
return;
}
if (Update != null) Update(this, EventArgs.Empty);
};
Now I want to call this delegate on B.ascx btn click
protected void btnHdnAnswer_Click(object sender, EventArgs e)
{
// How to call above delegate..
}
Please help me in this

Make your delegate a proper method.
btnUpdate.Click += delegate { DoUpdate(); }
...
public void DoUpdate()
{
if (MaxLength.HasValue && txtText.Text.Length >= MaxLength.Value)
{
lblError.Text = string.Format(Resources.ErrorMessage_FieldLength, MaxLength);
return;
}
if (Update != null) Update(this, EventArgs.Empty);
}
Make sure the Id of your control is set to generate a member for it in the code-behind:
<Project:A runat="server" ID="MyBControl"/>
Then call it from your B (parent) control:
protected void btnHdnAnswer_Click(object sender, EventArgs e)
{
MyBControl.Update();
}

Related

crystal report viewer next page not working

I am using visual studio 2010 and crystal report 13.0
The report viewer displays the first page properly. But the next page button is not working. If i click on next page button then it shows loading message and stays there only.None of the report viewer controls are working.
please help me out
I found the solution.
Manually add the Page_Init() event and wire it up in the InitializeCompnent() with
this.Init += new System.EventHandler(this.Page_Init).
Move the contents of Page_Load to Page_Init().
Add if (!IsPostBack) condition in PageInIt.
protected void Page_Init(object sender, EventArgs e)
{
if (!IsPostBack)
{
ReportDocument crystalReportDocument = new ReportDocumment();
crystalReportDocument.SetDataSource(DataTableHere);
_reportViewer.ReportSource = crystalReportDocument;
Session["ReportDocument"] = crystalReportDocument;
}
else
{
ReportDocument doc = (ReportDocument)Session["ReportDocument"];
_reportViewer.ReportSource = doc;
}
}
Instead of manually identifying the moment to bind, you could use the CrystalReportViewer AutoDataBind property in combination with the DataBinding event.
Autobind definition:
// Summary:
// Boolean. Gets or sets whether automatic data binding to a report source is
// used. If the value is set to True, the DataBind() method is called after
// OnInit() or Page_Init().
[Category("Data")]
[DefaultValue(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool AutoDataBind { get; set; }
You could use this property in the following manner:
In the ASPX:
<CR:CrystalReportViewer ID="_reportViewer" runat="server" AutoDataBind="true" OnDataBinding="_reportViewer_DataBinding" />
And in the ASPX.CS:
protected void _reportViewer_DataBinding(object sender, EventArgs e)
{
if (!IsPostBack)
{
ReportDocument crystalReportDocument = new ReportDocumment();
crystalReportDocument.SetDataSource(DataTableHere);
_reportViewer.ReportSource = crystalReportDocument;
Session["ReportDocument"] = crystalReportDocument;
}
else
{
ReportDocument doc = (ReportDocument)Session["ReportDocument"];
_reportViewer.ReportSource = doc;
}
}
Done! Shift your Page load Event to Page Init Event.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
int pageIndex =((CrystalDecisions.Shared.PageRequestContext)
CrystalReportViewer1.RequestContext).PageNumber;
//Bind Report with filter and datasource
string ControID = GetPostBackControlName(this);
//get and check Crystal Report Navigation button event after Bind Report
if (ControID == null)
{
((CrystalDecisions.Shared.PageRequestContext)
CrystalReportViewer1.RequestContext).PageNumber = pageIndex;
}
}
}
public string GetPostBackControlName(Page Page)
{
Control control = null;
string ctrlname = Page.Request.Params["__EVENTTARGET"];
if (ctrlname != null && ctrlname != String.Empty)
{
control = Page.FindControl(ctrlname);
}
else
{
string ctrlStr = String.Empty;
Control c = null;
foreach (string ctl in Page.Request.Form)
{
if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
{
ctrlStr = ctl.Substring(0, ctl.Length - 2);
c = Page.FindControl(ctrlStr);
}
else
{
c = Page.FindControl(ctl);
}
if (c is System.Web.UI.WebControls.Button ||
c is System.Web.UI.WebControls.ImageButton)
{
control = c;
break;
}
}
}
if (control == null)
{
return null;
}
else
{
return control.ID;
}
}

SelectedIndexChanged not firing in ascx?

I use masterpage.In ascx page my selectedindexchange event not firing.
This is my code:
My ascx :
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="FilterList.ascx.cs"
Inherits="F8.B2B.WEB.UserControls.Common.FilterList.FilterList" %>
<asp:UpdatePanel UpdateMode="Always" runat="server">
<ContentTemplate>
<div id="filterList" runat="server">
</div>
</ContentTemplate>
</asp:UpdatePanel>
My ascx.cs:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
createFilterLists();
}
}
private void createFilterLists()
{
ListBox dpList = new ListBox()
{
ID = ControlID
};
dpList.Items.Clear();
if (lst_ListItem != null)
{
foreach (ListItem item_ in lst_ListItem)
{
dpList.Items.Add(item_);
}
dpList.Items[0].Selected = true;
dpList.AutoPostBack = true;
dpList.EnableViewState = true;
dpList.SelectedIndexChanged += new EventHandler(myListBox_SelectedIndexChanged);
filterList.Controls.Add(dpList);
}
}
protected void myListBox_SelectedIndexChanged(object sender, EventArgs e)
{
// might be entered on change
}
Because your list box is dynamically generated by code, you need to add it in every page load even if it is a postback.
Create dynamic controls and add event handlers in the OnInit event
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
CreateControls();
myDataGrid.SomeEventHandler += new ...
}
Bind data and fill controls in the OnLoad event
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
FillControls();
myDataGrid.DataSource = somedatasource;
myDataGrid.DataBind();
}
}
private void CreateControls()
{
ListBox dpList = new ListBox()
{
ID = ControlID
};
dpList.AutoPostBack = true;
dpList.EnableViewState = true;
dpList.SelectedIndexChanged += new EventHandler(myListBox_SelectedIndexChanged);
filterList.Controls.Add(dpList);
}
private void FillControls()
{
dpList.Items.Clear();
if (lst_ListItem != null && lst_ListItem.Count > 0)
{
foreach (ListItem item_ in lst_ListItem)
{
dpList.Items.Add(item_);
}
dpList.Items[0].Selected = true;
}
}

SiteMapResolve does not fire

I am getting trouble that SiteMapResolve fires on some pages and doesn't on other.
This is my code.
protected void Page_Load(object sender, EventArgs e)
{
SiteMap.SiteMapResolve += new SiteMapResolveEventHandler(this.ChangeMapPath);
}
private SiteMapNode ChangeMapPath(Object sender, SiteMapResolveEventArgs e)
{
if (SiteMap.CurrentNode != null)
{
// Clone the current node and all of its relevant parents.
SiteMapNode currentNode = SiteMap.CurrentNode.Clone(true);
SiteMapNode tempNode = currentNode;
if (clientId != 0 && tempNode.Title.Equals("Client Notes"))
{
tempNode.Url = tempNode.Url + EncryptQueryString("ParentId=" + clientId.ToString());
}
if (clientId != 0 && tempNode.ParentNode != null && (tempNode.ParentNode.Title.Equals("Client Contacts")))
{
tempNode.ParentNode.Url = tempNode.ParentNode.Url + EncryptQueryString("ParentId=" + clientId.ToString());
}
else if (tempNode.ParentNode != null)
tempNode.ParentNode.Url = tempNode.ParentNode.Url;
return currentNode;
}
return null;
}
Thanks.
Try replace your code
SiteMap.SiteMapResolve += new SiteMapResolveEventHandler(this.ChangeMapPath);
to
foreach (SiteMapProvider mapProvider in SiteMap.Providers)
{
mapProvider.SiteMapResolve += ChangeMapPath;
}
I know this is an old question, but just in case anyone else is still dealing with this issue, the following solution works for me.
It appears that there is an issue with SiteMapResolveEventHandler not ever being removed, so the first event handler that is added, will be the one that gets called after that point.
https://blogs.msdn.microsoft.com/asiatech/2012/11/29/asp-net-case-study-sitemapresolveeventhandler-memory-leakage/
So, you can do exactly as the original poster has done, but you also need to add the following to each page that adds the SiteMapResolveEventHandler.
protected void Page_UnLoad(object sender, EventArgs e)
{
SiteMap.Provider.SiteMapResolve -= new SiteMapResolveEventHandler(this.ChangeMapPath);
}
It should call the appropriate handler on each page if you have forced the removal on previous pages.
Alternatively, instead of using the Page_Unload, you could place the
SiteMap.Provider.SiteMapResolve -= new SiteMapResolveEventHandler(this.ChangeMapPath);
line of code at the beginning of the ChangeMapPath method.
What worked for me better and easier to understand / maintain:
Create an interface with a handler method:
public interface ISiteMapResolver
{
SiteMapNode SiteMapResolve(object sender, SiteMapResolveEventArgs e);
}
subscribe to each event in the Application_Start method in global.asax
foreach (SiteMapProvider siteMapProvider in SiteMap.Providers)
siteMapProvider.SiteMapResolve += Provider_SiteMapResolve;
}
Then implement this method
SiteMapNode Provider_SiteMapResolve(object sender, SiteMapResolveEventArgs e)
{
var handler = e.Context.CurrentHandler as ISiteMapResolver;
return handler != null ? handler.SiteMapResolve(sender, e) : null;
}
This way you can implement ISiteMapResolverin each page you are interested to modify the node, e.g.
public SiteMapNode SiteMapResolve(object sender, SiteMapResolveEventArgs e)
{
if (SiteMap.CurrentNode == null) return null;
var node = SiteMap.CurrentNode.Clone(true);
node.Url += "?productId=" + ProductId; // Access page property, no problem. Page_Load event already fired.
note.Title = "Product " + Product;
// Modify node.ParentNode here if needed.
return node;
}

The problem when loading a web user control dynamicly

The web user control: FilterLabel
<span style=" display:block; float:left; margin:5px; padding: 5px; border: 1px inset #000000; font-family: Tahoma; font-size: small;">
<asp:Label ID="lblFilterDisplay" runat="server" Text="Product/Service: This is a testing"></asp:Label>
<asp:ImageButton ID="btnRemove" runat="server" ImageUrl="~/Images/remove.png" OnClick="btnRemove_Click" />
And the part of behind codes for this web user control:
public event EventHandler RemoveClick;
......
public void btnRemove_Click(object sender, EventArgs e)
{
if (RemoveClick != null)
RemoveClick(this, EventArgs.Empty);
}
Next, the web user control "FilterLabel" will be used in another web user control "FilterList":
<%# Register TagPrefix="uc" TagName="FilterLabel" Src="~/Controls/FilterLabel.ascx" %>
<asp:Panel ID="FilterList" runat="server" Width="100%" GroupingText="Filter List" CssClass="filterList">
</asp:Panel>
And the part of behind codes of this web user control is:
protected override void OnInit(EventArgs e)
{
if (IsPostBack)
{
BindFilters();
}
}
public void BindFilters()
{
List<FilterLabel> filters = Filters;
foreach (FilterLabel filter in filters)
{
FilterList.Controls.Add(filter);
}
}
public List<FilterLabel> Filters
{
get
{
List<FilterLabel> filters = Session["Filters"] as List<FilterLabel>;
if (filters == null)
{
filters = new List<FilterLabel>();
}
return filters;
}
}
public void AddFilter(string filterName, string filterContent, string filterValue = null)
{
FilterLabel filter = LoadControl("~/Controls/FilterLabel.ascx") as FilterLabel;
filter.ID = "Filter";
filter.FilterContent = filterContent;
filter.FilterName = filterName;
filter.Value = filterValue;
filter.RemoveClick += new EventHandler(RemoveFilter);
List<FilterLabel> filters = Filters;
filters.Add(filter);
Session["Filters"] = filters;
BindFilters();
}
private void RemoveFilter(object sender, EventArgs e)
{
//some handling codes
}
So now the problem is the btnRemove_Click event isn't activated when I click the image button "btnRemove".
You should try with bubble event. with your solution you will need on each postback to rebind event handler on each usercontrol for existing filters
public int FilterCount
{
get{
if(ViewState["filter_count"] == 0){
FilterCount = 0;
}
return (int)ViewState["filter_count"];
}
set{
ViewState["filter_count"] = value;
}
}
protected void RecreateFilterControlls()
{
for(int i =0; i < FilterCount; i++){
FilterLabel filter = LoadControl("~/Controls/FilterLabel.ascx") as FilterLabel;
FilterList.Controls.Add(filter);
filter.RemoveClick += new EventHandler(RemoveFilter);
}
}
protected override void OnInit(EventArgs e)
{
if (IsPostBack)
{
RecreateFilterControlls();
}
}
// this is for button which will add new FilterLabel UserControl
protected void AddNewFilter_Click(object sender, EventArgs e)
{
// just create filter
AddFilter(<FilterNameTextBox|combobox>, <FilterContentTextBox>, <filterValue>);
}
public void AddFilter(string filterName, string filterContent, string filterValue = null)
{
FilterLabel filter = LoadControl("~/Controls/FilterLabel.ascx") as FilterLabel;
filter.ID = "Filter";
filter.FilterContent = filterContent;
filter.FilterName = filterName;
filter.Value = filterValue;
filter.RemoveClick += new EventHandler(RemoveFilter);
// increament filter count
FilterCount++;
}
private void RemoveFilter(object sender, EventArgs e)
{
//some handling codes
//remove control which caused this event
FilterList.Controls.Remove(sender); // or you will need to ask for IndexOf(sender);
FilterCount--;
}
the rest will be handled by ViewState it self, so you don't need to bind data back to FilterLabel back

Problem with page lifecycle

The qustion was modified by me to show a complete picture.
I have a basic question:
code behind:
protected void Page_Load(object sender, EventArgs e)
{
int firstPageIndex = 0;
int lastPageIndex = 5;
if (TotalPageNumber > 5)
{
if ((TotalPageNumber - PageIndex) <= 5)
firstPageIndex = TotalPageNumber - 5;
firstPageIndex = PageIndex < 3 ? 0 : PageIndex - 2;
}
else
{
firstPageIndex = 0;
lastPageIndex = TotalPageNumber;
}
for (int i = firstPageIndex; i < firstPageIndex + lastPageIndex; i++)
{
LinkButton lnk = new LinkButton();
lnk.CommandArgument = i.ToString();
lnk.Click += new EventHandler(lblPageNumber_Click);
lnk.ID = "lnkPage" + (i + 1).ToString();
lnk.Text = (i + 1).ToString();
plcPagerHolder.Controls.Add(lnk);
} }
int _pageIndex;
public int PageIndex
{
get
{
object objPage = ViewState["_pageIndex"];
if (objPage == null)
{
_pageIndex = 0;
}
else
{
_pageIndex = (int)objPage;
}
return _pageIndex;
}
set {ViewState["_pageIndex"] = value; }
}
protected void lnkPagerNext_Click(object sender, EventArgs e)
{
PageIndex = PageIndex == TotalPageNumber - 1 ? 0 : PageIndex + 1;
}
The problem is with Page_Load event, I expect to get new PageIndex after the linkbutton is clicked.
Update:
My Foo adds new controls to the page, based on provide Page index so I guess I can't put it in Prerender.
Two options
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Foo (PageIndex);
}
}
protected void LinkButton_Click(object sender, EventArgs e)
{
PageIndex = int.Parse(((LinkButton)sender).CommandArgument);
Foo (PageIndex);
}
or
protected void Page_PreRender(object sender, EventArgs e)
{
Foo (PageIndex);
}
you can place Foo (PageIndex) in Page_LoadComplete event instead of Page_Load, i.e.
protected void Page_LoadComplete(object sender, EventArgs e)
{
Foo (PageIndex);
}
LoadComplete event is raised after Control events.
Edit:
LoadComplete is the earliest place where you can safely access new pageindex and also you can add there another controls, but that is possible also in PreRender.
And you will, but Page_Load gets called before the event handler for the linkbutton .. so, you can't really expect it to be changed yet.

Resources