Using same form on multiple pages? - asp.net

I am writing an application, and I have a user form, which will be the same for the users and the administrators on different pages.
I want to only create the form once, and then be able to put it on two different aspx files.
I tried it with the "control", but it then gets really complicated trying to access fields on the control from the aspx page to do the calculation, etc.
is there another way to do this? creating a form in one place, be able to add it to any aspx page, and have easy access to it's controls?

It's not very difficult at all. You can provide an accessor method or make the control inside public.
Example: A page which displays the contents of a TextBox inside a control, when a button is pressed.
Control
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="WebApplication1.WebUserControl1" %>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
Page
<form runat="server">
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<Test:Control ID="ctlTest" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</form>
Code (If TextBox1 is public)
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = ctlTest.TextBox1.Text;
}
Or you could have, in the code of the control
public string GetText()
{
return TextBox1.Text;
}
And in the aspx code page
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = ctlTest.GetText();
}
What is so difficult about that?!

you have to create MasterPage:
http://msdn.microsoft.com/en-us/library/wtxbf3hh.aspx
so that you can share common controls between pages. Master pages can be nested, too. You can access controls on master page from child page via Master.FindControl("abc")
EDIT: it seems that you want to reuse common piece of functionality, then you might want to use user control, like in this example:
http://msdn.microsoft.com/en-us/library/3457w616.aspx

you created the control, and do not use findControl() method to access the control that inside you UserControl, that is not feasible or proper solution.
Better to use Properies. Define Properties, so your control can be generalised and you can use that on multiple pages.

Related

Using Code Nuggets as property values

I have the following code
<asp:Content ID="Content1" runat="server">
<asp:Label runat="server" ID="Label1" Text="<%= MyHelperClass.Value%>"></asp:Label>
<%= MyHelperClass.Value%>
</asp:Content>
The Label doesn't work, it has the Text <%= MyHelperClass.Value%> the next row returns the expected value.
Question: can i use those code nuggets to set values of the property of an control?
Why it's working outside and not with Control?
Well <%= %> is called Content Code Nuggets because they inject content in the html which is sent by server to browser. It does the work of Reponse.Write. We use this mainly to call any code written in code behind file for example, you have a simple method in your code behind:-
public string UserCity()
{
return "London";
}
Then you can call it from aspx page like this:-
You live in <%= UserCity() %>.
Content code nuggets used to inject the html to response at the last in PreRender event and thus it's called late binding. This is the main reason why it is NOT working with your control.
How to fix this?
You can use the data binding code nuggets (<%# %>). These are used with DataBound controls but you can force the Page's DataBound or control's DataBound method to bind your control like this:-
<asp:Label runat="server" ID="Label1" Text="<%# MyHelperClass.Value%>"></asp:Label>
Call DataBind method in code behind:-
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Page.DataBind();
}
}

Why is Page.PreviousPage always null?

I am experimenting with cross-page posting by following this MSDN article. I have this code:
CrossPagePosting1.aspx
<form id="form1" runat="server">
<h1>Page 1</h1>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><br />
<asp:Button ID="Button1" runat="server" Text="Button" PostBackUrl="CrossPagePosting2.aspx"/>
</form>
CrossPagePosting2.aspx
<form id="form1" runat="server">
<h1>Page 2</h1>
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
</form>
CrossPagePosting2.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
TextBox TextBox1 = (TextBox)Page.PreviousPage.FindControl("TextBox1");
Label1.Text = TextBox1.Text;
}
This code above produces a NullReferenceException at Page.PreviousPage. Why?
This is an ASP.Net 4.0 application.
It uses FriendlyUrls, which is the default.
NOTE: I do NOT want the previous page to be strongly-typed, e.g. using the PreviousPageType directive. According to the referenced article, this shouldn't be necessary.
I found that Friendly URLS might get you this problem. By default, the Web Forms template includes ASP.NET Friendly URLs.
When you use the default WebForm from visual Studio, the AutoRedirectMode is set to Permanent. This makes you request into a "GET" and since you are using Friendly URLS, you can’t evaluate the PreviousPage.
Workarounds:
If you want a "POST" action then set the AutoRedirectMode =
RedirectMode.Off (this will give you PreviousPage info but only from
non-Friendly-Url pages [ex: www.you.com/mypage.aspx], however this
will get you an error if you try to access the Friendly-Url page [ex:
www.you.com/mypage] << no .aspx).
If you want the PreviousPage information you will have to set the
previous post directive in you webpage <%# PreviousPageType
VirtualPath="~/Page1.aspx" %> OR maybe use the Server.Transfer in a
OnClick Method.
The problem here was being caused by FriendlyUrls, which were installed by default on the test site I was working in. I disabled FriendlyUrls, and it worked.
I think following article will helps you.
http://csharpdotnetfreak.blogspot.com/2009/08/cross-page-posting-in-aspnet.html
there are two method how to use Cross Page Posting PostBack
The reason this is happening is simply because you did not set the postbackurl property correctly.
If CrossPagePosting2.aspx is at root of your program change postbackurl to ~/CrossPagePosting1.aspx
You do not need to add the <%# PreviousPageType %> directive when using postbackurl property. using PreviousPage.FindControl(id) will search the form elements that are posted using postbackurl property
Try this
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack && PreviousPage != null)
{
Page page = PreviousPage;
Label1.Text = ((TextBox)page.FindControl("TextBox1")).Text;
}
}

Keep a value accessible in Page.Init between postbacks in asp.net

Ok, I've already learned that in order to keep the dynamic (created) controls and their viewstate in asp.net we must (re)create them in the Page init event, so they already exist within the page's control hierarchy before the view state is loaded.
As it says in this article.
There is no problem to achieve this behaviour if the criteria to create these controls is outside the web environment, for example a database. But what should I do if what I use to decide how many dynamic controls I have to create is actually a value that is in the controls?
I try to explain it with an example, maybe it's clearer:
Let's say that we have a textbox and two buttons. In the textbox I write the number of how many dynamic controls I want to create, for example 4 checkbox. When I hit the button1 the controls should be created. No problem. Then I check some checkboxes and hit the button2 just to fire a postback. Now I should recreate the controls in the page init event, like we said before, in order to maintain the controls and their state.
And here comes the problem. Because of I'm in the init stage I have no viewstate so I'm no able to access the value in the textbox that tells me how many dynamic checkbox should I create.
I thought that storing the value in the session object would do the trick, but it doesn't. The session object is no accessible as well.
Where can I save the value that it'll be accessible from the init event too?
Thanks and sorry for the long post!
First thing - textbox value is not stored/retrieved from view state, you cannot get textbox value from viewstate.
Coming to actual problem, here is the sequence of (imp) events init -> load view state -> bind postback data -> page load. You can retrieve textbox value only after bind postback data event (which actually takes posted data and binds to the textbox control).
In init only option is to use Request.Form{"textboxid"] to get the textbox value.
You are on the right track.
If you use TextBox, you do not need another ViewState to keep track of how many controls has been created, because TextBox control has its own ViewState already.
You can use either Page_Init or Page_Load to load control back.
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs"
Inherits="WebApplication2010.WebForm1" %>
<!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></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox runat="server" ID="NumberTextBox" />
<asp:Button runat="server" ID="CreateControlButton"
OnClick="CreateControlButton_Click"
Text="Create Control" />
<br />
<asp:PlaceHolder runat="server" ID="PlaceHolder1"></asp:PlaceHolder>
</div>
</form>
</body>
</html>
using System;
using System.Web.UI;
namespace WebApplication2010
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
int ids;
if (Int32.TryParse(NumberTextBox.Text, out ids))
{
for (int i = 0; i < ids; i++)
{
Control ctrl = Page.LoadControl("WebUserControl.ascx");
ctrl.ID = i.ToString();
PlaceHolder1.Controls.Add(ctrl);
}
}
}
}
protected void CreateControlButton_Click(object sender, EventArgs e)
{
}
}
}
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="WebUserControl.ascx.cs"
Inherits="WebApplication2010.WebUserControl" %>
<asp:CheckBox runat="server" ID="CheckBox1" />
<asp:Button runat="server" ID="Button1" OnClick="Button_Click"
Text="Post Back" />
<asp:Label runat="server" ID="Label1" />
<br />
using System;
namespace WebApplication2010
{
public partial class WebUserControl : System.Web.UI.UserControl
{
protected void Button_Click(object sender, EventArgs e)
{
Label1.Text = " This control was posted back.";
}
}
}
This is the common paradox with page lifecycle when you work with code behind. For example, you save the editing customerid in viewstate but controls need to bind on init to be able to read their posted values.
Best real life solution is to do what bound controls do on postback, call explicilately the LoadPostBackData on IPostBackDataHandler interface that all controls implement, after you have created them in Page Load event.
You should create an extension method for Controls and call it when needed:
control.DataBind();
control.LoadPostedData(); // extension method

Set Custom ASP.NET UserControl variables when its in a Repeater

<%# Register Src="~/Controls/PressFileDownload.ascx" TagName="pfd" TagPrefix="uc1" %>
<asp:Repeater id="Repeater1" runat="Server" OnItemDataBound="RPTLayer_OnItemDataBound">
<ItemTemplate>
<asp:Label ID="LBLHeader" Runat="server" Visible="false"></asp:Label>
<asp:Image ID="IMGThumb" Runat="server" Visible="false"></asp:Image>
<asp:Label ID="LBLBody" Runat="server" class="layerBody"></asp:Label>
<uc1:pfd ID="pfd1" runat="server" ShowContainerName="false" ParentContentTypeId="55" />
<asp:Literal ID="litLayerLinks" runat="server"></asp:Literal>
</ItemTemplate>
</asp:Repeater>
System.Web.UI.WebControls.Label lbl;
System.Web.UI.WebControls.Literal lit;
System.Web.UI.WebControls.Image img;
System.Web.UI.WebControls.HyperLink hl;
System.Web.UI.UserControl uc;
I need to set the ParentItemID variable for the uc1:pdf listed inside the repeater.
I thought I should be able to find uc by looking in the e.Item and then setting it somehow. I think this is the part where I'm missing something.
uc = (UserControl)e.Item.FindControl("pfd1");
if (uc != null) { uc.Attributes["ParentItemID"] = i.ItemID.ToString(); }
Any thoughts would be appreciated.
Also tried this with similar results... when I debug inside my usercontrol (pfd1) the parameters I am trying to set have not been set.
uc = (UserControl)e.Item.FindControl("pfd1");
if (uc != null)
{
uc.Attributes.Add("ContainerID", _cid.ToString());
uc.Attributes.Add("ParentItemId", i.ItemID.ToString());
}
UPDATE: It looks like my controls are not connected by a namespace. I've wrapped by the parent control (Layer) and the PressFileDownlad control in a namespace "MyControls". Also updated their Inherits reference on the aspx to read "MyControls.xxxxx". I'm able to type "MyControls.Layer" inside the code on layer.aspx.cs but I'm not able to get "MyControls.PressFileDownload"
If you implement ParentItemID as a public property in your user control, then you should be able to set it declaratively, e.g:
<asp:Repeater id="Repeater1" ...>
<ItemTemplate>
<uc1:pfd ID="pfd1" runat="server" ParentItemId='<%# Eval("ItemID") %>' ... />
Martin is right you should be able to set it in declarative way (in case your property is public) .
But your way should also work (just cast it properly)
((PressFileDownload)e.Item.FindControl("pfd1")).ParentItemId = 0;
The best way is to implement the OnDataBinding event for the user control. I try to stay away from putting code inline in the aspx using webforms if possible.
When the repeater gets bound, for each item that is bound, the OnDataBinding will fire for your user control and your handler can do what it needs. You don't have to go searching for the controls.
Here is an example:
// in your aspx
<uc1:pfd ID="pfd1" runat="server" ShowContainerName="false" ParentContentTypeId="55"
OnDataBinding="pfd1_DataBinding" />
// in your codebehind implement the OnDataBinding event
protected void pfd1_DataBinding(object sender, System.EventArgs e)
{
pfd uc = (pfd)(sender);
uc.ContainerID = _containerID.ToString();
uc.ParentItemID = Eval("ItemID");
// Here you can do more like access other items like hidden fields
// or cached objects or even other controls etc... Skys the limit.
}
EDIT: Notice from your comment you require more data than what is found in the datasource. In this case what I usually do is just make private member variables in the .cs that I store data in. So when you have the container ID just store it in a variable that will be accessible.
Eg in your .cs for your page:
public partial class _TestPage : System.Web.UI.Page
{
private int _containerID { get; set; }
Then when you load the data just set the _containerID property and it will be accessible in the OnDataBinding event. Just make sure you are binding after you have set the _containerID.

ASP.NET linkbutton visible property issue

I'm using a public variable called IsAdmin in the code behind of an aspx page.
public partial class _news : System.Web.UI.Page
{
public bool IsAdmin = false;
protected void Page_Load(object sender, EventArgs e)
{
if (User.Identity.Name.Contains("admin"))
{
IsAdmin = true;
}
else
{
IsAdmin = false;
}
}
And i use the property Visible='<%#IsAdmin%>' to assign to panels which i want to show if the user is an admin in the aspx design of the page. Strangely it works for the linkbuttons i've put on the repeater.
<asp:Panel ID="Panel1" runat="server" Visible='<%#IsAdmin%>'>
<asp:LinkButton ID="LinkButton2" runat="server" PostBackUrl='<%# "news_edit.aspx? Action=edit&id=" + Convert.ToString( Eval("news_id")) %>Edit</asp:LinkButton>
<asp:LinkButton ID="LinkButton3" runat="server" PostBackUrl='<%# "news.aspx?Action=delete&id=" + Convert.ToString( Eval("news_id")) %>'>Delete</asp:LinkButton>
</asp:Panel>
and it works fine, however outside the repeater i've put another linkbutton without a panel
<asp:LinkButton ID="LinkButton4" runat="server" PostBackUrl="~/news_edit.aspx?action=new" Visible='<%#IsAdmin%>'>Add New Item</asp:LinkButton>
but the visible property doesn't work on it! I tried putting it inside a panel too and setting it's visible property but that too didn't work.
So i have following doubts
1)what is the issue?
2)what is the technical name when we use references like '<%#IsAdmin%>' in the design page
3)Does page load happen before page is rendered of after page is rendered?
Thanks
<%# %> is the syntax used for accessing databound fields. Since you are likely databinding the Repeater control at some point, these expressions will be evaluated.
Since you are likely not calling databind on the Panel and the Linkbuttons outside of the Repeater, these expressions will not be processed. You can probably change them to something like
<%= IsAdmin.ToString() %>
and get the result you want.
Check this great blog entry for more information on the differences.
Also, Page Load happens before the page is rendered. Rendering the page is the last thing that happens in the ASP.Net page lifecycle.

Resources