How to implement LayoutTemplate with a PlaceHolder - asp.net

In my own server control, I would like to implement something similar to the ListView:
<asp:ListView runat="server">
<LayoutTemplate>
<asp:PlaceHolder runat="server" id="itemPlaceholder" />
</LayoutTemplate>
</asp:ListView>
I have created an ITemplate property, I can set the layout in the aspx page, and I am doing ITemplate.InstantiateIn(myControl).
But I can't figure out how to insert controls at the placeholder. I'm guessing it would be something like MyTemplate.FindControl("itemPlaceholder").Controls.Add(myControl). I tried casting to the type of my ITemplate, but I get the error:
Unable to cast object of type 'System.Web.UI.CompiledTemplateBuilder' to type 'MyNamespace.MyLayoutTemplate'
What am I missing?
Edit: I just found this: http://www.nikhilk.net/SingleInstanceTemplates.aspx Control developers can define templates to be single instance using metadata which causes the ID'd controls within the template contents to be promoted to the page level... The parser and code-generator together work behind the scenes to add member fields, and initialize them at the right time.. It seems to be only for user controls? I tried Page.FindControl() after doing this but it didn't find anything.

Ok, this was simply a matter of user error. I instantiated the ITemplate in a Panel, so obviously Page.FindControl() (which is not recursive) wouldn't work. Once I did Panel.FindControl(), everything worked.

In the past I have used this library with sucess
http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx

Related

Gridview inside of form running at server throws "'GridView' must be placed inside aform tag with runat=server"

I've seen a looot of questions about this and I've tried to overload/override VerifyRenderingInServerForm method and it isn't helping (the compiler complains if I try overrides).
To be sure:
In the master page, we have:
<form id="form1" runat="server">
so it definitely is inside a form/server tag.
The gridview has:
<asp:GridView
ItemStyle-CssClass="Item"
ID="grdInfo"
runat="server"
CssClass="grdCss"
Width="100%"
CellPadding="3"
AutoGenerateColumns="false"
HeaderStyle-CssClass="Header"
RowStyle-CssClass="Item"
AlternatingRowStyle-CssClass="AltItem"
AllowSorting="false"
AllowPaging="false">
....
Unlike other people, I'm not trying to render excel. I am, however, attempting to bind to a enumerable collection:
Public Class colInfoSet
Inherits CollectionBase
We use this type of object elsewhere without problems.
I just found out what the problem is. When the master page and child page/controls are loaded, the grid isn't rendered because it has no rows. The grid is then retrieved via ajax and then populated.
Since it was not rendered when the page was rendered, it cannot be added to the control tree.
Hence it doesn't work.
The solution I will be going with is to use a repeater instead.

vb asp.net : A way to avoid repeating a code in common in ItemTemplate and EditItemTemplate

I'm a newbie in asp.net.
When using FormView, there is a big amount of code in ItemTemplate, EditItemTemplate and InsertItemTemplate which is almost identical.
For example:
<asp:ListBox ID="ListBox2" runat="server" Rows="1" CssClass="field"
DataSourceID="StatusList" DataTextField="DESCRIPTION"
DataValueField="STAT_ID" SelectedValue='<%# Bind("STAT_ID") %>'>
</asp:ListBox>
(Note: at the exception that Eval() would be used instead of Bind() in ItemTemplate)
I've been trying to avoid repeating this code but without the expecting result:
ListView allows the use of LayoutTemplate - but I didn't see any examples that insert this kind of code in LayoutTemplate. And inserting this code in LayoutTemplate would result in an error.
DetailView allows to produce code automatically but I'd like to use a specific design (for ex. using "fieldset" that encompasses some fields).
What would be the best way to avoid repeating this kind of code ?
You don't have to much choice about seperately specifying the Bind/Eval part, but you do have some control over the other pieces. You can make a custom UserControl that contains your layout.
Usually I include a property on this usercontrol called "Mode" which I either set to Edit or View, then based off of this property I change enabled/visible properties on the controls. You'll also need to include a property for each value you want bound/displayed in the usercontrol.
Put some labels, textboxes, etc... in your designer and hook them up to properties in your code behind, put the usercontrol on your page in your item/edit template and eval/bind to your data to the various properties (make sure to set the mode so it displays right).

Nested ASP.Net controls not defined

I have a couple of controls that are set to runat="server", but are showing up as "not declared" in the vb code behind. They are not being setup in the designer.vb file at all, even if the design.vb is re-created.
The only thing that I can think might be causing this is that the controls are inside of a custom control. The code looks something like this (it has been modified because of NDA):
<abc:MyCustomControl>
<additionalItems>
<asp:CheckBox id="coolCheckboxOfPower" runat="server" Text="Triple Rainbow!">
</asp:CheckBox>
</additionalItems>
</abc:MyCustomControl>
So using the example above, if I try to use coolCheckboxOfPower in my vb page, it says it is not declared.
It has been suggested to me that asp controls cannot be nested. Is this true, and if so, how do I get around that?
Asp controls can certainly be nested. Just look at asp:Panel, asp:ListView etc. You have to do some extra work when creating your control to enable this to happen. Namely you have to make have an ITemplate property on your control. Check out the following Building Templated Custom ASP.NET Server Controls to get you started

Two-way data binding of controls in a user control nested inside a FormView doesn't work

I'm trying to perform two-way data binding on the controls in my user control, which is hosted inside a FormView template:
<asp:ObjectDataSource runat="server" ID="ObjectDataSource"
TypeName="WebApplication1.Data" SelectMethod="GetItem" UpdateMethod="UpdateItem">
</asp:ObjectDataSource>
<asp:FormView runat="server" ID="FormView" DataSourceID="ObjectDataSource">
<ItemTemplate>
<uc:WebUserControl1 runat="server"></uc:WebUserControl1>
</ItemTemplate>
<EditItemTemplate>
<uc:WebUserControl1 runat="server"></uc:WebUserControl1>
</EditItemTemplate>
</asp:FormView>
The web user control:
<%# Control Language="C#" ... %>
<asp:TextBox runat="server" ID="TitleTextBox" Text='<%# Bind("Title") %>'>
</asp:TextBox>
The binding works fine when the FormView is in View mode but when I switch to Edit mode, upon calling UpdateItem on the FormView, the bindings are lost. I know this because the FormView tries to call an update method on the ObjectDataSource that does not have an argument called 'Title'.
I tried to solve this by implementing IBindableTemplate to load the controls that are inside my user control, directly into the templates (as if I had entered them declaratively). However, when calling UpdateItem in edit mode, the container that gets passed into the ExtractValues method of the template, does not contain the TextBox anymore. It did in view mode!
I have found some questions on SO that relate to this problem but they are rather dated and they don't provide any answers that helped me solve this problem.
How do you think I could solve this problem? It seems to be such a simple requirement but apparently it's anything but that...
My current workaround for this is, although rather cumbersome, to subclass the FormView class and use subclassed controls in it, implementing my own data binding logic (taking the data field name from a new property) instead of using the <%# %> syntax. Apparently, the code the latter generates is the real culprit here as it doesn't support this nested control scenario.
I ended up, using old asp include statement
<--%include file = "filename" -->
instead of using user controls for dealing with the code duplication issue.

How do I make the children appear in a custom webcontrol for ASP.NET?

For example, I have a custom control called SampleControl. To simplify things for this question, pretend I'm making just a Panel Control clone from scratch.
<CC:SampleControl ID="Sample1" runat="server">
<asp:Label ID="Label1" runat="server" Text="Hi"></asp:Label>
<asp:Button ID="Button1" runat="server" Text="Button1"></asp:Label>
</CC:SampleControl>
To Output:
<div id="Sample1">
<span id=Label1>Hi</span>
etc.....
</div>
Where the Code is:
public class SampleControl: WebControl
{
.....Render Stuff Goes Here.....
}
The ASP controls in the middle aren't being registered by ASP.NET. When I did a Reflector on the Panel control, I couldn't find out how they got the middle controls to render. It doesn't look like they are using a Templated Control.
When I do it, I get this error:
Parser Error
Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.
Any Ideas?
First, [ParseChildren(false)] attributes lets parser know that you want your control to treat nested content as child controls.
Then make sure that somewhere in Render the RenderChildren method is called. It's the default implementation of System.Web.UI.Control.Render(), so you can do base.Render(writer) in your overriden Render method.

Resources