I have 5 files.
Default.aspx
Search.ascx
SearchSQL.ascx
Grid.ascx
GridSQL.ascx
I have registered the ascx files in the default.aspx page and use properties to expose the controls to the default page. And that works great.
My issue is how do I send data back and fourth between the different ascx pages? If I register on any of those it will give me a Circular file reference error.
Using public properties, I have the Search.ascx registered on the GridSQL.ascx to pass the search parameters into Gridsql string, and then the GridSQL.ascx on the Grid.ascx file to pass the sql string to the grid databind.
There has got to be a much easier way to pass data BACK & FOURTH between pages, or am I wrong? When you try to register on the other page to pass data back to the page that sent it, you get the circular file reference error. I have heard a few resolutions like changing file structure, which I have tried, and also about Batch, but that kills performance. Believe i have spent days trying to find resolutions on this. I was going to comment on some questions but Stack does not allow me until I have 50 Rep.
My company is requiring us to use all separate files from now on and I just cant believe this is the best way to communicate between user controls.
Proper way is you want to bubble up the child control's event to parent.
Then let parent to forward the event to other controls.
Note: Here is the demo. You might want to rename delegates and methods which make sense to your scenario.
Search (User Control which fires the event)
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="Search.ascx.cs" Inherits="DemoWebForm.Search" %>
<asp:TextBox runat="server" ID="SearchTextBox" />
<asp:Button runat="server" ID="SearchButton"
Text="Search" OnClick="SearchButton_Click" />
public delegate void MessageHandler(string searchText);
public partial class Search : System.Web.UI.UserControl
{
public event MessageHandler SearchText;
protected void SearchButton_Click(object sender, EventArgs e)
{
SearchText(SearchTextBox.Text);
}
}
GridSql (User Control)
Finally, GridSql.ascx receives the search text.
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="GridSql.ascx.cs" Inherits="DemoWebForm.GridSql" %>
<asp:Label runat="server" ID="SearchTextLabel"/>
public partial class GridSql : System.Web.UI.UserControl
{
public void SearchTextMethod(string searchText)
{
SearchTextLabel.Text = searchText;
}
}
Parent
<%# Page Language="C#" AutoEventWireup="true"
CodeBehind="Parent.aspx.cs" Inherits="DemoWebForm.Parent" %>
<%# Register src="~/Search.ascx" tagname="Search" tagprefix="uc1" %>
<%# Register src="~/GridSql.ascx" tagname="GridSql" tagprefix="uc2" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<uc1:Search ID="Search1" runat="server" />
<uc2:GridSql ID="GridSql1" runat="server" />
</form>
</body>
</html>
public partial class Parent : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Search1.SearchText += m => GridSql1.SearchTextMethod(m);
}
}
Related
I have made a simple project to explain my problem.
This is my Default.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="WebApplication1.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="txtDate" runat="server"></asp:TextBox>
<asp:CustomValidator ID="cusDate"
runat="server"
ValidateEmptyText="true"
OnServerValidate="DateValidate"
ValidationGroup="DateVal"
ControlToValidate="txtDate"
ErrorMessage="Date error"></asp:CustomValidator>
<asp:ImageButton ID="btnSaveDate"
CausesValidation="true"
ValidationGroup="DateVal"
ImageUrl="~/Images/save_32.png"
runat="server" />
</div>
</form>
</body>
</html>
And this is my Default.aspx.cs
using System;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack) <<<<<<BREAKPOINT 1 HERE
{
}
}
protected void DateValidate(Object source, ServerValidateEventArgs args)
{
args.IsValid = false; <<<<<<BREAKPOINT 2 HERE
}
}
}
I set two breakpoints, as shown above, and run the application. When I click "btnSaveDate" it first stops at breakpoint 1 and then at breakpoint 2. I thought it would stop at breakpoint 2 first, then reload the page and then stop at breakpoint 1.
Is there something wrong in the code or should it behave like this?
I have read many articles about this and tried a lot of different solutions, but no one has worked so far.
According to the ASP.NET Page Life Cycle, the Postback event handling happens after the Load event.
If the request is a postback, control event handlers are called. After
that, the Validate method of all validator controls is called, which
sets the IsValid property of individual validator controls and of the
page. (There is an exception to this sequence: the handler for the
event that caused validation is called after validation.)
A postback means that a client is making an http request to the server and, every time a request arrives to the server, the Page Life Cycle stages are executed in this exact order. So the second answer is no, is not possible to enter in the breakpoint 2 then before entering the breakpoint 1.
I'm new to ASP.NET C# and trying to accomplish the following:
Have a Default.aspx page with two user controls (Control1.ascx and Control2.ascx)
Both user controls are within UpdatePanels.
Need the TextBox on the second user control disabled until the TextBox on the first control has been validated. Once validated, TextBox on user control2 needs to be enabled.
These user controls will be re-used on multiple pages.
Help is appreciated. If I need to post some code let me know.
Here's code sample:
Default.aspx
<%# Page Title="Home Page" Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%# Register src="Control1.ascx" tagname="CTL1" tagprefix="uc1" %>
<%# Register src="Control2.ascx" tagname="CTL2" tagprefix="uc2" %>
<uc1:CTL1 Id="CTL1" runat="Server" UpdateMode="Conditional"/>
<uc2:CTL2 Id="CTL2" runat="Server" UpdateMode="Conditional"/>
Default.aspx.cs
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
Control1.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="Control1.ascx.cs" Inherits="Control1" %>
<asp:UpdatePanel ID="UpdatePanel_Fld1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:TextBox ID="TextBox_Fld1" runat="server" Enabled="True" ></asp:TextBox>
<asp:ImageButton ID="ImageButton_ValidateFld1" runat="server" ImageUrl="~/images/validate.jpg"
onclick="ImageButton_ValidateFld1_Click" />
<asp:Label ID="LabelFld1Summary" runat="server" > </asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
Control1.ascx.cs
public partial class Control1 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void ImageButton_ValidateFld1_Click(object sender, ImageClickEventArgs e)
{
LabelFld1Summary.Text = "Validated";
}
}
Control2.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="Control2.ascx.cs" Inherits="Control2" %>
<asp:UpdatePanel ID="UpdatePanel_Fld2" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:TextBox ID="TextBox_Fld2" runat="server" Enabled="False"></asp:TextBox>
<asp:ImageButton ID="ImageButton_ValidateFld2" runat="server" ImageUrl="~/images/validate.jpg"
onclick="ImageButton_ValidateFld2_Click" />
<asp:Label ID="LabelFld2Summary" runat="server" > </asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
Control2.ascx.cs
public partial class Control2 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void ImageButton_ValidateFld2_Click(object sender, ImageClickEventArgs e)
{
LabelFld2Summary.Text = "Validated";
}
}
I suggest go with simple javascript or involve jQuery to do the enable/disable thing, add some js code into a client side validation script
I suggest getting your scenario working with synchronous postbacks first, then adding the updatepanels into the mix. As a rough sketch, in a server-side OnClick handler for some button or other you can set the enabledness of the second control based on the result of validation of the first control. Then, you just need to make sure you call Update() on Control2.ascx's UpdatePanel when the asynch postback targeting Control1.ascx's UpdatePanel happens.
That said, this is going to be mildly annoying from a user's perspective. Unless the first control modulates a great deal of UI below it (like, switching to a separate control set entirely), why not just let your users enter text into both fields and validate on the combination of them?
I agree with Simon. jQuery would probably be the easiest way to accomplish this. you can use jQuery's ajax methods to make calls to WebMethods if you need to interact with the code behind for any reason.
I've used update panels and the ICallbackEventHandler interface (http://madskristensen.net/post/Asynchronous-GridView-in-5-simple-steps.aspx is a good example of its use) with some success.
While I tend to stay away from UpdatePanels, I realized that they use the ICallbackEventHandler interface behind the scenes and I probably make more work for myself. The only benefit of doing it the way I did is that I don't have a bunch of garbage sitting in my ViewState (UpdatePanels love ViewState), as I've persisted it in the server-side session state.
In my case, the reason for going with the ICallbackEventHandler method over using jQuery's ajax calls and WebMethods in the code behind was that I wanted to have access to non-static fields (including my web controls). Turns out I needed to manually persist the data displayed on the page in session or otherwise and probably ended up making more work for myself in the end. It was a good chance to learn something new, but the benefits I gained from having access to the pages controls were minimal/non-existent.
I created Master page which has got mainNavigator panel on top of page that is a web user control(BuildMenu.ascx). I am filling UC Menu in master page's loading :
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="IntermMaster.master.cs" Inherits="MyProject.IntermMaster" EnableViewState="true" %>
<%# Register src="Utils/BuildMenu.ascx" tagname="BuildMenu" tagprefix="uc1" %>
>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<uc1:BuildMenu ID="BuildMenu2" runat="server" />
</div>
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
This is loading in postback event:
BuildMenu.ascx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Fill Menu from DataBase (Compare SiteMap...)
}
Every post back BuildManu.ascx is loading every time tihs is really bored me. How can i solve it. I want to do only one time load BuildMenu.ascx (in master page)
Unless you want to use frames (and you probably do not), the control has to be reloaded each time so it can be rendered. The best you can do is to use server-side output caching so that it takes less processing time to load the control.
To do output caching, put this in your page:
<%# OutputCache Duration="[Number of Seconds]" VaryByParam="None" %>
The load method WILL be called every time a postback occures (except for AJAX pages, but let's not go there). Take a look at the ASP.NET page lifecycle.
What you can do is just return from the controls Load event if the value of IsPostBack is true.
However, if the control in question is static (or almost static) in content you could try using output cashing on the server, that way the control will be loaded once in a while, and the rest of the times, the server will just use it's cashed copy.
i have a better idea why dont you sue a session it will help you
make like this ::
protected void Page_Load(object sender, EventArgs e)
{
if session(ispostback") <> "menuloaded"
{
// Fill Menu from DataBase (Compare SiteMap...)
Session("ispostback")="menuloaded"
}
this will work for sure
I've created very simple web site for the test purposes. Only one master page and one content page.
My content page looks like this:
<%# Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<div id="TestDiv1">bla bla</div>
<div id="TestDiv2">ble ble</div>
</asp:Content>
Now, based on some condition I would like to show/hide a given div. So I am trying to reach one of those divs by Controls collection, like this:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ContentPlaceHolder myContent = (ContentPlaceHolder)this.Master.FindControl("ContentPlaceHolder1");
myContent.FindControl("TestDiv1").Visible = false; //this is not working
}
}
}
}
But the above example is not working. None of the two div control exists in the myContent.Controls collection. If I place for example a TextBox on my content page, I can reach it through Controls.
So what should I do to be able to access the div control?
your divs are HTMLcontrols, try to add them the tag runat="server"
<div id="TestDiv1" runat="server">bla bla</div>
That should solve your issue.
You need to set runat="server" on the divs.
I recently started using Masterpages, the thing is I would like to add text in code to an asp:Content tag.
So my content page markup code is:
<%# Page Language="C#" MasterPageFile="~/Template.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ASP_Test_WebApp.Default" %>
<asp:Content id="TEST" ContentPlaceHolderID="Main" Runat="Server" />
So now I would like to add Contents to the "TEST" id incode.
But my in code doesn't recognize TEST. If I don't use a masterpage and I give an id to a tag my in code reconigzes it, but now that I started using masterpages it doesn't.
What am I doing wrong?
Content tags don't have any UI on their own, you need to add controls inside them that you can then address in your code e.g.
<%# Page Language="C#" MasterPageFile="~/Template.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ASP_Test_WebApp.Default" %>
<asp:Content id="TEST" ContentPlaceHolderID="Main" Runat="Server" >
<asp:label runat="server" id="MyLabel"/>
</asp:content>
public partial class Default: System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyLabel.Text = "StackOverflow rocks!"
}
}
You don't need that ID. Try to add your content like: this.Controls.Add(mycontentcontrol)