I'm trying to create a rendering template for my forms which need complex validations treatments.
the rendering template is working fine wwith :
<XmlDocuments>
<XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<Display>ListForm</Display>
<Edit>ChaisTemplate</Edit>
<New>ChaisTemplate</New>
</FormTemplates>
</XmlDocument>
</XmlDocuments>
and with my ascx :
<%# Control AutoEventWireup="true" CodeBehind="ChaisTemplate.ascx.cs"
Inherits="TransactionsFormsTemplates.ControlTemplates.ChaisTemplate, TransactionsFormsTemplates"
Language="C#" %>
<%# Assembly Name="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Register TagPrefix="SharePoint" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
Namespace="Microsoft.SharePoint.WebControls" %>
<%# Register TagPrefix="wssuc" TagName="ToolBar" Src="~/_controltemplates/ToolBar.ascx" %>
<%PageLoad(this, null);%>
<SharePoint:RenderingTemplate ID="ChaisTemplate" runat="server">
.....
but I can't have any control mappings in my code behind (in the webapp bin with cas policies, and it's correctly deployed)
this :
<asp:TextBox runat="server" ID="test"></asp:TextBox>
is null when it comes to :
public partial class ChaisTemplate : System.Web.UI.UserControl
{
protected TextBox test;
so everytime I call test.Text on functions, I get a nullreferenceexception, because test is never mapped to my ascx textbox. why ?
plus, the PageLoad is never called like in classic asp.net pages, even with <%PageLoad(this, null);%> at the beginning.
however every event works :
<asp:Button runat="server" ID="button" OnClick="button_OnClick"/>
this will actually call button_OnClick in my code behind. But all my properties are null because not mapped.
did I miss something?
I'v been doing it like this. Take this as an example RenderingTemplate:
<SharePoint:RenderingTemplate ID="ParentItemsListView" runat="server">
<Template>
<table cellpadding=0 cellspacing=0>
<tr><td nowrap class="UserGenericHeader"><asp:Label ID="lblParentItems" runat="server" /></td></tr>
<tr><td><SharePoint:ListViewByQuery ID="listViewByQuery" runat="server" /><br /></td></tr>
</table>
</Template>
</SharePoint:RenderingTemplate>
Then in Render event i can reference these controls like this:
[SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
protected override void Render(HtmlTextWriter output)
{
if (this.Visible)
{
Label lblParentItems = this.TemplateContainer.FindControlRecursive<Label>("lblParentItems");
lblParentItems.Text = "Pievienotie " + this.ChildList.Title;
ListViewByQuery listView = TemplateContainer.FindControlRecursive<ListViewByQuery>("listViewByQuery");
listView.List = this.ChildList;
...
base.Render(output);
}
}
Ahh, yes, i use a handy extension function
public static T FindControlRecursive<T>(this Control parentControl, string id) where T : Control
{
T ctrl = default(T);
if ((parentControl is T) && (parentControl.ID == id))
return (T)parentControl;
foreach (Control c in parentControl.Controls)
{
ctrl = c.FindControlRecursive<T>(id);
if (ctrl != null)
break;
}
return ctrl;
}
However i had an issue where i inherited from SaveButton that i couldn't reference a control. In that case i changed so that i inherit from FormControl and i could find my control under this.Controls.
Also note that you cannot reference controls up until OnLoad event has executed (i.e if you're in OnLoad function, call base.OnLoad(e) before referencing controls.
Why is it so? I guess because it's not like you are having a template and then code behind (working with the same class/object), but it's more like you are rendering that ascx template in a different class/object file.
Related
I have following project structure where web application may contain user controls from the same web project or from a separate class library. The issue is in Default.aspx.cs, when I execute usercontrol2.SetValues(); I receive NullReferenceException since for some reason textbox2 is null. I've tried using EnsureChildControls(); but it does not help either. Should I register or invoke these usercontrols in some other way? Why does not it work out-of-box?
User control in web project
WebUserControl1.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="WebApplication1.WebUserControl1" %>
<asp:TextBox runat="server" ID="textbox1"></asp:TextBox>
WebUserControl1.ascx.cs
namespace WebApplication1
{
public partial class WebUserControl1 : System.Web.UI.UserControl
{
public void SetValues()
{
textbox1.Text = "Hello";
}
}
}
User control in class library
WebUserControl2.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl2.ascx.cs" Inherits="ClassLibrary1.WebUserControl2" %>
<asp:TextBox runat="server" ID="textbox2"></asp:TextBox>
WebUserControl2.ascx.cs
namespace ClassLibrary1
{
public partial class WebUserControl2 : System.Web.UI.UserControl
{
public void SetValues()
{
textbox2.Text = "world";
}
}
}
Main page
Default.aspx
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<%# Register tagPrefix="web" tagName="WebUserControl1" src="WebUserControl1.ascx" %>
<%# Register TagPrefix="web" Namespace="ClassLibrary1" Assembly="ClassLibrary1" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<web:WebUserControl1 runat="server" ID="usercontrol1"></web:WebUserControl1>
<web:WebUserControl2 runat="server" ID="usercontrol2"></web:WebUserControl2>
</asp:Content>
Default.aspx.cs
using System;
using System.Web.UI;
namespace WebApplication1
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
usercontrol1.SetValues(); // OK
usercontrol2.SetValues(); // NullReferenceException
}
}
}
Using ascx usercontrols from a different assembly is not possible.
I think you should look at this problem this way. Your classlibrary is compiled into a dll-file. This is the only thing that is available for your webapplication. The ‘ascx’ doesn’t get compiled into the dll, and is not available.
If you really want to keep some controls separated from your web-project, I think there are a few options:
Convert your usercontrol to a customcontrol. Custom controls are a bit more difficult to create, but it is certainly not impossible. This way you really get a re-usable control.
See also this question; it addresses your problem and there’s also a link to an algorithm which ‘converts’ an ascx usercontrol to a custom control. (I didn’t test that)
Asp.NET user control referenced from another project/dll has NULL properties
Make sure your ascx files are available to the web-project, by publishing to a path in your output. Then use LoadControl to load them serverside. This could work, but I also think some of the reusability from your classlibrary is lost.
I am using the following in ASP.NET webcontrols :
<%# OutputCache Duration="86400" VaryByParam="none" %>
This means that the control will be null on reload if it is already added to the cache. The problem is that on some page I want to hide this control and it would be great if this could be done from the MasterPage codebehind file(where it is loaded).
I have tried this :
if (Request.AppRelativeCurrentExecutionFilePath.ToLower().EndsWith("/sites/MySite/default.aspx") || Request.AppRelativeCurrentExecutionFilePath.ToLower().EndsWith("MySite.net"))
{
if(topGames_Mini1 != null)
{
//Load control
topGames_Mini1.visible=true;
}
}
else
{
Page.LoadControl("topGames_Mini1").Visible = false;
}
It will however throw the following exception in the else :
The file '/Bradspel/sites/MySite/community/topGames_Mini1' does not
exist.
you should better place the UserControl inside a Placeholder control. Then simply hide/show the Placeholder depending on your conditions.
The Placeholder does not render any tags for itself, so there is NO overhead of outer HTML tags.
I Assume you must have registered your UserControl in your Master page. So, place the userControl now inside a PlaceHolder control.
<asp:ContentPlaceHolder ID="MainContent" runat="server"><!-- Of Master Page -->
<asp:PlaceHolder ID="place1" runat="server">
<uc1:Test ID="Test1" runat="server" /><!-- Our User Control-->
</asp:PlaceHolder>
</asp:ContentPlaceHolder>
and in Code behind::
protected void Page_Load(object sender, EventArgs e)
{
if( _Some_Condition_)
place1.Visible = true;
else
// Hide PlaceHolder and thus all controls inside it
place1.Visible = false;
}
I'm facing a weird problem with my asp.net buttons.
All was fine, I was coding a webpart with some ajax panels and buttons, and it was just so near to be finished when a wild error appeared. All my buttons were firing the same method despite I didn't told then so.
Well, I found it was due to a known issue : http://forums.asp.net/t/1567526.aspx/1
I tried to delete the called method to see if the other buttons would go back to their assigned methods, and since then, no more event is fired by buttons.
No more... Never...
I put back the method, created a new webpart with new code, restored a backup of my site, reset my server, restarted Visual Studio, And finally I'm trying to create a whole new VS solution with a whole new code. I've just a page with one lonely asp button, And nothing happens...
ascx file :
<%# Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%# Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%# Import Namespace="Microsoft.SharePoint" %>
<%# Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="PublicationUserControl.ascx.cs" Inherits="CripmeeWebParts.Publication.PublicationUserControl" %>
<asp:Button ID="Valider" runat="server" Text="Valider" />
ascx.cs file
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
namespace CripmeeWebParts.Publication
{
public partial class PublicationUserControl : UserControl
{
protected override void OnLoad(EventArgs e)
{
EnsureChildControls();
base.OnLoad(e);
}
protected override void CreateChildControls()
{
base.CreateChildControls();
Valider.Click += new EventHandler(Valider_Click);
}
void Valider_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
}
I've tied all this :
attach event on the ascx code or on the CreateChildControls, use onCommand event, place button in a <form>, attach debugger to w3 process to see if it go through all my methods.
I'm just out of ideas...
Thank you for reading, any suggestion would be usefull.
here comes the solution I've found.
I still don't know why the event disappeared, but I notice that they are not fired only when I display the webpart from administration panel (site action>settings>webpart library> click on my custom webpart). If I add my webpart to a test page, all is working fine. If someone else have the same issue, I hope he will read this and avoid the week I've lost...
Thank you all for your time and answers :)
just put this
Valider.Click += new EventHandler(Valider_Click);
in Page_Load() or Page_Init() I can't see where you call CreateChildControls()
try
Valider= new Button();
Valider.Text = "Valider";
Valider.Click += new EventHandler(VAlider_Click);
Controls.add(Valider)
in your CreateChildControls
Your button needs an OnClick event declared
<asp:Button ID="Valider" runat="server" Text="Valider" OnClick="Valider_Click"/>
or Call your CreateChildControls in Page_Load
Hello (sorry for the poor title)
I have a user control which loads different additional user controls based on some conditions like this:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="SubPage.ascx.cs" Inherits="SubPage" %>
<%# Register Src="<srcA>" TagName="A" TagPrefix="CTRL" %>
<%# Register Src=">srcB>" TagName="B" TagPrefix="CTRL" %>
<% if (someValue == 1) { %>
Loading user control A..
<CTRL:A runat="server" />
<% } else { %>
Loading user control B..
<CTRL:B runat="server" />
<% } %>
The result will look correct; the expected content is displayed. But I noticed that even though someValue != 1 and control B is displayed, control A is still loaded behind the scenes (page load is called).
Why is this? And what would be a better approach? Thanks.
Page_Load is called because you handle this event.
Don't try to load them in this way but use the Visible-Property instead from codebehind.
Expose a public function that the controller(in your case SubPage.ascx) calls after it changed the visible state to load the content of the UserControl. Controls that aren't visible won't be rendered as html at all.
Loading controls dynamically if you don't really need can cause unnecessary ViewState- or Event-Handling issues. Here are some other disadvantages mentioned regarding dynamic UserControls.
You need to call LoadControl method instead
<% if (someValue == 1) { %>
Loading user control A..
Page.LoadControl(("~\ExampleUserControl_A.ascx");
<% } else { %>
Loading user control B..
this.LoadControl(("~\ExampleUserControl_B.ascx");
<% } %>
Code Front:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="SubPage.ascx.cs" Inherits="SubPage" %>
<%# Register Src="<srcA>" TagName="A" TagPrefix="CTRL" %>
<%# Register Src="<srcB>" TagName="B" TagPrefix="CTRL" %>
<asp:placeholder id="plhControls" runat="server" />
Code Behind:
if (someValue == 1) {
CTRLA ctrlA = (CTRLA)LoadControl("~/Controls/ctrlA.ascx");
plhControls.Controls.Add(ctrlA);
} else {
CTRLB ctrlB = (CTRLB)LoadControl("~/Controls/ctrlB.ascx");
plhControls.Controls.Add(ctrlB);
}
so I've finally started building custom controls instead of using functions which return chunks of HTML ;) But I'm running into a problem. I want to pass parameters to the control, say, "X":
<some:MessageControl runat="server" X=<%# "asd" %> />
My code behind looks like this:
public partial class MessageControl : System.Web.UI.UserControl
{
String x = "";
public String X
{
get { return x; }
set { x = value;}
}
}
When I output the value of x in the control,
x: <%= X %>
it is empty.
If I pass on "asd" directly as in
<some:MessageControl runat="server" X="asd" />
X gets the correct value.
What's happening here? How can I get this to work? Any suggestions are appreciated,
Nicolas
Edit: Some more context. Basically I want to be able to insert the control on a number of pages without settings its properties in the code behind, but still be able to set its visibility by calling a (varying) method from the containing page.
<%# Page Language="c#" Src="MyPage.aspx.cs" AutoEventWireup="true" Inherits="MyPage" %>
<%# Register Src="MessageControl.ascx" TagName="MessageControl" TagPrefix="some" %>
<html>
<body>
<some:MessageControl runat="server" Visible=<%# SomeBoolMethodFromContaining Page%> />
</body>
</html>
For <%= SomeMethods or Property %> expression you need to call DataBind() method in parent page or control that contains this expression on OnPageLoad event or another.
For example here code behind:
protected void Page_Load(object sender, EventArgs e)
{
DataBind();
}
protected string Hello
{
get { return "hello";}
}
Here html part of the page:
<asp:Literal runat="server" Id="Literal1" Text="<%= Hello %>"/>
For Visible property use code above and <%# Method or Property%> expression. For text use <%= %> expression. It renders output as a plain text.
Hope it will help you with your question.
Best regards, Dima.
Use this:
X='<%# "asd" %>'
Note the single quotes.