For some business related reasons I made a wizard navigation user control. Pretty simple: Next/Previous/Finish buttons.
Each of the parent pages that use this nav user control have a SaveData function, which saves the data and does a bunch of other stuff.
When the user clicks Next/Previous/Finish I want to call the parent's SaveData function before redirecting to the other page. How should I do this or can you recommend a better way (code examples if possible please)?
Thanks in advance!
UserControl should not call Parent's function. It is not a good design.
Instead, you want to bubble up the event from UserControl to the Parent page.
Note: my project's namespace is DemoWebForm.
MyUserControl.ascx
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="MyUserControl.ascx.cs"
Inherits="DemoWebForm.MyUserControl" %>
<asp:Button runat="server" ID="NextButton"
OnClick="NextButton_Click" Text="Next" />
<asp:Button runat="server" ID="PreviousButton"
OnClick="PreviousButtonn_Click" Text="Previous" />
<asp:Button runat="server" ID="FinishButton"
OnClick="FinishButton_Click" Text="Finish" />
MyUserControl.ascx.cs
public partial class MyUserControl : System.Web.UI.UserControl
{
public event ClickEventHandler NextClicked;
public event ClickEventHandler PreviousClicked;
public event ClickEventHandler FinishClicked;
protected void NextButton_Click(object sender, EventArgs e)
{
if (NextClicked != null)
{
NextClicked(sender, e);
}
}
protected void PreviousButtonn_Click(object sender, EventArgs e)
{
if (PreviousClicked != null)
{
PreviousClicked(sender, e);
}
}
protected void FinishButton_Click(object sender, EventArgs e)
{
if (FinishClicked != null)
{
FinishClicked(sender, e);
}
}
}
Parent.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Parent.aspx.cs"
Inherits="DemoWebForm.Parent" %>
<%# Register Src="MyUserControl.ascx" TagName="MyUserControl" TagPrefix="uc1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<uc1:MyUserControl ID="MyUserControl1" runat="server"
OnNextClicked="MyUserControl1_NextClicked"
OnPreviousClicked="MyUserControl1_PreviousClicked"
OnFinishClicked="MyUserControl1_FinishClicked" />
<asp:Literal runat="server" ID="MessageLiteral" />
</form>
</body>
</html>
Parent.aspx.cs
public partial class Parent : System.Web.UI.Page
{
protected void MyUserControl1_NextClicked(object sender,EventArgs e)
{
MessageLiteral.Text = "Next button was clicked";
}
protected void MyUserControl1_PreviousClicked(object sender, EventArgs e)
{
MessageLiteral.Text = "Previous button was clicked";
}
protected void MyUserControl1_FinishClicked(object sender, EventArgs e)
{
MessageLiteral.Text = "Finish button was clicked";
}
}
you only need the delegate:
public delegate void ClickEventHandler(object sender, EventArgs e);
public event ClickEventHandler NextClicked;
Related
when i use image control with updatepanel in asp.net, compiler gives an error : NullReference exception,
please any body help me. so what should be done to avoid such problem?
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div>
<asp:AsyncFileUpload ID="flduserphoto" runat="server"
OnClientUploadComplete="OnClientAsyncFileUploadComplete"
OnUploadedComplete="OnAsyncFileUploadComplete" Width="374px" />
<asp:Image runat="server" ID="imgPhoto" Width="150px" />
</div>
</ContentTemplate>
</UpdatePanel>
code file is,
public partial class Registration_frmUserRegistration : System.Web.UI.Page
{
DataTable dt;
#region FileUploadControl Section
protected void OnAsyncFileUploadComplete(object sender, AsyncFileUploadEventArgs e)
{
if (flduserphoto.FileBytes != null)
{
lblgender.Text = "asdf";
Context.Session.Add("SessionImage", flduserphoto.FileBytes);
}
}
#endregion
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSave_Click(object sender, EventArgs e)
{
BALUserAddress objUserAddress = new BALUserAddress();
objUserAddress.UserType = ddlusertype.Text;
byte[]imageByte = new byte[flduserphoto.PostedFile.ContentLength];
objUserAddress.ProfilePicture=imageByte;
objUserAddress.ParentID = "0";
objUserAddress.RelationWith="Self";
objUserAddress.RegistrationDateTime= DateTime.Now;
string msg = objUserAddress.SaveUserDetails();
lblMsg.Text=msg;
mpMsg.Show();
}
}
this is my code file please check it
Try this one in form tag
<form id="form1" enctype="multipart/form-data" method="post" runat="server">
I have a div in default.aspx with img inside as follow
<div id="sTab" class="tabs firsttab" runat="server">
<asp:Image ID="sTabImg" src="images/home.png" runat="server" />
Activities
</div>
I want to perform some action on click of the div in ASP.NET (not in javascript).
I tried the following
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
}
sTabImg.Attributes["onclick"] = ClientScript.GetPostBackEventReference(this, "ClickDiv");
}
protected void ClickDiv()
{
Label2.Text = "helo got it";
}
The page is getting refreshed and when i debugged the issue, its not entering the ClickDiv function..What wrong here..
From Here
public partial class _Default : System.Web.UI.Page, IPostBackEventHandler
{
protected void Page_Load(object sender, EventArgs e)
{
div1.Attributes["onclick"]=ClientScript.GetPostBackEventReference(this,"ClickDiv");
}
protected void Div1_Click()
{
// Do something
}
#region IPostBackEventHandler Members
public void RaisePostBackEvent(string eventArgument)
{
if (!string.IsNullOrEmpty(eventArgument))
{
if (eventArgument == "ClickDiv")
{
Div1_Click();
}
}
}
#endregion
}
You have to implement the IPostBackEventHandler Interface.
Why not use ImageButton?
<%# Page Language="C#" AutoEventWireup="True" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>ImageButton Sample</title>
<script language="C#" runat="server">
void ImageButton_Click(object sender, ImageClickEventArgs e)
{
Label1.Text = "You clicked the ImageButton control at the coordinates: (" +
e.X.ToString() + ", " + e.Y.ToString() + ")";
}
</script>
</head>
<body>
<form id="form1" runat="server">
<h3>ImageButton Sample</h3>
Click anywhere on the image.<br /><br />
<asp:ImageButton id="imagebutton1" runat="server"
AlternateText="ImageButton 1"
ImageAlign="left"
ImageUrl="images/pict.jpg"
OnClick="ImageButton_Click"/>
<br /><br />
<asp:label id="Label1" runat="server"/>
</form>
</body>
</html>
And you can see some examples here.
I have two UserControls - UserControl1.ascx and UserControl2.ascx in PageDefault.aspx:
How I can call the method (GetLabelText() in UserControl1.ascx) from UserControl2.ascx using event bubbling?
This is my example code - When I click on the button (UserControl2Button1 in UserControl1.ascx) - I want to call the method GetLabelText() from UserControl2.ascx - using event bubbling.
PageDefault.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="PageDefault.aspx.cs" Inherits="TelerikAjaxEvents.PageDefault" %>
<%# Register TagPrefix="uc" TagName="UserControl1" Src="~/UserControl1.ascx" %>
<%# Register TagPrefix="uc" TagName="UserControl2" Src="~/UserControl2.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Page Default</title>
</head>
<body>
<form id="form1" runat="server">
UserControl1:
<uc:UserControl1 ID="UserControl1" runat="server" />
UserControl2:
<uc:UserControl2 ID="UserControl2" runat="server" />
</form>
</body>
</html>
UserControl1.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="UserControl1.ascx.cs" Inherits="TelerikAjaxEvents.UserControl1" %>
<asp:Label ID="UserControl1Label1" runat="server"></asp:Label>
UserControl1.ascx.cs
public partial class UserControl1 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void GetLabelText()
{
UserControl1Label1.Text = "Text is Visible";
}
}
UserControl2.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="UserControl2.ascx.cs" Inherits="TelerikAjaxEvents.UserControl2" %>
<asp:Button ID="UserControl2Button1" runat="server" Text="Send"
onclick="UserControl2Button1_Click" />
UserControl2.ascx.cs
public partial class UserControl2 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void UserControl2Button1_Click(object sender, EventArgs e)
{
//Call method from UserControl1 (GetLabelText()) - Show Label text - USING BUBBLE EVENT
}
}
There are many ways to go about this. Mark's answer hints at what was classically known as event bubbling using a built in functionality part of System.Web.UI.Control base control. However, it's a simple exercise to expose your own event, bind to it, and bubble up events through a control hierarchy. For more details on using BubbleEvent in ASP.NET read the following. Please keep in mind that both of these MSDN articles were written for .NET 1.1
Bubbling an Event
Event Bubbling Control Sample
K. Scott Allen does a good job at demonstrating exactly what an "event bubbling" implementation looks like in his post: Event Bubbling From Web User Controls in ASP.NET (C#) . See the following modification to your example for inspiration.
UserControl1 with GetLabelText()
public partial class UserControl1 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void GetLabelText()
{
UserControl1Label1.Text = "Text is Visible";
}
}
UserControl2 with exposed BubbleClick event handler that callers can subscribe to.
public partial class UserControl2 : System.Web.UI.UserControl
{
protected Button UserControl2Button1;
protected void Page_Load(object sender, EventArgs e)
{
}
public event EventHandler BubbleClick;
protected void OnBubbleClick(EventArgs e)
{
if(BubbleClick != null)
{
BubbleClick(this, e);
}
}
protected void UserControl2Button1_Click(object sender, EventArgs e)
{
// do some stuff
OnBubbleClick(e);
}
}
PageDefault subscribes to UserControl2's BubbleClick event handler and executes UserControl1.GetLabelText()
public partial class PageDefault : WebPage
{
UserControl1 userControl1;
UserControl2 userControl2;
protected void Page_Load(object sender, EventArgs e)
{
UserControl2.BubbleClick += RootBubbleClickHandler;
}
protected void RootBubbleClickHandler(object sender, EventArgs e)
{
if (sender is UserControl2)
{
// subscribe UserControl1 to UserControl2 click event and do something
userControl1.GetLabelText();
}
// check for other controls with "BubbleClicks"
}
}
Event Bubbling is a poorly understood concept in ASP.NET WebForms. It does exist (and is used by most of the databound controls), but is often mistaken for the simpler concept of "implement an event in a user control" (as K Scott Allen does).
The core of event bubbling is that the event travels up through the control hierarchy until it is handled or hits the root. This allows some centralization of handler code. It is implemented using the Control.RaiseBubbleEvent and Control.OnBubbleEvent methods. The main use case is controls with a lot of child controls (think Repeaters, ListViews, etc.). Instead of subscribing to each individual control, the Repeater catches them all in it's OnBubbleEvent and raises a single ItemCommandEvent for them.
If you really wanted to use event bubbling (as opposed to K. Scott's example), it'd look something like:
class Page {
override bool OnBubbleEvent(object sender, EventArgs e) {
var btn = sender as Button;
if (btn == null) return false;
// You may want to do further checking that the source is what you want
// You could use CommandEventArgs to do this
this.uc1.GetLabelText();
return true;
}
}
The sequence of events goes like this:
- Button Clicked
- Button RaiseBubbleEvent
- UserControl OnBubbleEvent returns false (default, since you didn't override)
- Page OnBubbleEvent
Can you try declaring the UserControl1 as public property(e.g. "UserControl1") on the PageDefault.aspx and then in the UserControl2, use Parent.Page.UserControl1.GetLabelText()?
Setting TableSection = TableRowSection.TableHeader after the grid is bound works initially, putting the header row in thead. After a postback (where the grid is not re-bound) the header row reverts to the table body. I expect the header row to stay in thead; can someone explain why this is not the case or what I am doing wrong?
Sample:
Click the button to cause a postback. The header is not orange after the postback since it's not in thead anymore.
aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="gridtest.aspx.cs" Inherits="ffff.gridtest" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<style type="text/css">
thead th { background-color:Orange;}
</style>
</head>
<body>
<form id="form1" runat="server">
<div><asp:Button ID="Button1" runat="server" Text="Button" />
this button is here just to trigger a postback</div>
<asp:GridView ID="gv1" runat="server"></asp:GridView>
</form>
</body>
</html>
code
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ffff
{
public partial class gridtest : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
gv1.DataBound += new EventHandler(gv1_DataBound);
if (!IsPostBack) { BindGrid(); }
}
void Page_PreRender(object sender, EventArgs e)
{
if (gv1.HeaderRow != null)
System.Diagnostics.Debug.WriteLine(gv1.HeaderRow.TableSection); // still TableHeader after postback
}
void gv1_DataBound(object sender, EventArgs e)
{
if (gv1.HeaderRow != null)
{
gv1.HeaderRow.TableSection = TableRowSection.TableHeader;
}
}
private void BindGrid()
{
gv1.DataSource = this.Page.Controls;
gv1.DataBind();
}
}
}
Use the Pre_Render_Complete event instead to add the table section. This will ensure the thead section is always added. As you are currently doing it on DataBound the section will only be added when the data is bound.
protected override void OnPreRenderComplete(EventArgs e)
{
if (gv1.Rows.Count > 0)
{
gv1.HeaderRow.TableSection = TableRowSection.TableHeader;
}
}
Feel free to change the row check I use to checking the Header Row exists as you currently do.
You must set TableSection after DataBind method.
gv1.DataSource = this.Page.Controls;
gv1.DataBind();
gv1.HeaderRow.TableSection = TableRowSection.TableHeader;
Just put the below code in prerender event of gridview
protected void gv_PreRender(object sender, EventArgs e)
{
if (gv.Rows.Count > 0)
{
gv.UseAccessibleHeader = true;
gv.HeaderRow.TableSection = TableRowSection.TableHeader;
}
}
I am using a UserControl Which is present in the Master Page. I need to access a Master page control in the UserControl. I need your suggestions.
The Scenario is A label is present in the Master Page. Based upon selections in the usercontrol i need to modify the masterpage label. The UserControl is present in the Master page itself not in the content place holder.
Create a public method (or public property) in the master page to modify your label and in the UserControl you are able to call it, through the Page.master object:
YourMasterPageClass master = Page.master as YourMasterPageClass;
if(master != null)
{
master.YourEditMethod("hello");
}
Quick and Easy way is to create event in control and handle in master like this:
//Control aspx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="TestControl.ascx.cs"
Inherits="TestControl" %>
<div style="width:300px;border:2px groove blue;">
<asp:Button ID="btn1" runat="server" Text="One" onclick="btn_Click" />
<asp:Button ID="btn2" runat="server" Text="Two" onclick="btn_Click" />
<asp:Button ID="btn3" runat="server" Text="Three" onclick="btn_Click" />
<asp:Button ID="btn4" runat="server" Text="Four" onclick="btn_Click" />
</div>
//Control C#
namespace Controls
{
public partial class TestControl : System.Web.UI.UserControl
{
public delegate void UserChoice(TestEventArgs e);
public event UserChoice OnUserChoice;
protected void btn_Click(object sender, EventArgs e)
{
if (OnUserChoice != null)
OnUserChoice(new TestEventArgs(((Button)sender).Text));
}
}
public class TestEventArgs : EventArgs
{
private string _value;
public TestEventArgs(string str)
{
_value = str;
}
public string Message
{
get { return _value; }
}
}
}
//MasterPage Code
protected void Page_Load(object sender, EventArgs e)
{
test1.OnUserChoice += new
Controls.TestControl.UserChoice(test1_OnUserChoice);
}
void test1_OnUserChoice(ROMS.Intranet.Controls.TestEventArgs e)
{
MasterLabel.Text = e.Message;
}
MasterLabel is name of the label in master page.
test1 is the control in master page.