My
ExpandingPanel
control is a templated control. It isn't a repeating databound control like
DataGrid or anything, but it's templated because it has two "views", and the
easiest way to do that was, it seemed, to make each view a
template.
This has caused me quite a few emails over the
months it has been around, because it is very confusing for those who are trying
to create the control from codebehind, and not declare it in an aspx. The reason
for this is because asp.net does a lot of behind-the-scenes magic when
templated controls are parsed and compiled. Every template you declare on the
page becomes its own class that implements ITemplate, and that class's
InstantiateIn method is called when the containing control needs to create
the template for rendering and such.
Most developers have no idea that this is going on,
and send me emails asking why ExpandingPanel1.Controls.Add(myControl) doesn't
work. I generally try to explain to them that they have to create a new class
that implements ITemplate, implement InstantiateIn to add the controls they
want, and then instantiate a new instance of that class for the templated
property of the control. One for each template in the control. At that point,
the developer either goes, "OK, got it" and does their thing, or goes "Wa huh?",
stops using ExpandingPanel, and handcodes their own implementation of the
control so they understand whats going on.
And then I get the email from the "OK I got it" guy
when he tries to figure out how to do databinding. OOOOF. This is not fun. Most
people just use that Container.DataItem property without even a small
understanding of where that hell that "Container" object comes from, or what
"DataItem" refers to, other than, "that seems to magicly hook up with my
data".
Now he has to understand that "Container" is
actually a code-generated property that refers to the individual row/item in the
outside control. So, for DataGrid, it's a DataGridItem. for Repeater, it's a
RepeaterItem. etc. But ExpandingPanel has no
ExpandingPanelItem, it's just the ExpandingPanel control itself. And here's the
kicker, Container only exists for autogenerated templates, and you have to
implement it yourself in the ITemplate class. And there's nothing in the vanilla
sdk that tells you how to do this afaik. BAH.
Sure, I know how to do it, it's generally the
NamingContainer of the control you get sent to instantiate into. But why the
hell does the page developer have to know this arcane stuff?
I think templates are a great idea, and they are
great for the visual designer -> asp.net runtime story. They suck for the
codebehind guy. why does he need to make an entire class and implement some
non-documented stuff, just to add controls to a container?
And then, as usual, I came up with a great idea. :)
I figured... I can't really do anything about the
way templating/ITemplate works. I need to have an object instance that
implements ITemplate. However, what I noticed is that almost all custom
implementations of ITemplate do the same thing. How about a RuntimeTemplate
class that can be used genericly for these ITemplate Control properties?
RuntimeTemplate has an Instantiate event. When the containing Control calls
instantiate on its ITemplate property, RuntimeTemplate simply raises its
event.
This is obviously not a complex class. In fact,
it's about 15 lines of code. but it changes the "create a new class, implement
ITemplate.." story to handling an event like so:
void Form_Init( Object sender,
EventArgs e ) {
Repeater1 = new
Repeater();
Form1.Controls.Add( Repeater1
);
RuntimeTemplate template = new
RuntimeTemplate();
template.Instantiate += new
InstantiateEventHandler( template_Instantiate
);
Repeater1.ItemTemplate =
template;
if ( !IsPostBack )
{
Repeater1.DataSource = new String[] { "one", "two", "three"
};
Repeater1.DataBind();
}
}
void template_Instantiate(
Object sender, InstantiateEventArgs e ) {
CheckBox InnerCheckBox
= new CheckBox();
InnerCheckBox.ID =
"InnerCheckBox";
InnerCheckBox.DataBinding += new EventHandler(
InnerCheckBox_DataBinding
);
e.Container.Controls.Add( InnerCheckBox
);
}
void
InnerCheckBox_DataBinding( Object sender, EventArgs e )
{
CheckBox InnerCheckBox = sender as
CheckBox;
RepeaterItem container = InnerCheckBox.NamingContainer
as RepeaterItem;
InnerCheckBox.Text =
container.DataItem.ToString();
}
"But Wait", you might say, "you didn't really fix
the databinding/container thing!" Ya, sorry, I haven't figured out a good way
around that yet. I'll let yall know when I do.
Just saw this from
Colt about his free cookbook delivery...
Being a
contributing author of the ASP.NET
Developer's Cookbook, I got the complimentary copy today!! Thanks to SAMS, Steve and Rob at first.
However, when I
get the mail from the lobby and discover that...
the envelop WAS OPENED!!
I don't know why, but the envelop
was obviously opened. The book and 2 leaflets are still here,
everything alright, but the cover was a bit dirty (You know,
the cover is white in color so I can idenity the 'dirty' or 'fingerprint'
easily)
The mail and envelop don't have any chop or identification
for "censor" from Custom Department or UPS company, but ... I think I will
know who did it if I saw anyone post a "Review" on this book earlier than me,
as I'm pretty sure I'm the first one who own this book in Hong Kong.... Will
see...
and as another
person who recently received a free copy...
Mine was messed up
and dirty too. Nothing was missing... no pages torn or
anything.
Just the cover was
covered in some kind of grime, and the book had a "I've been sitting on a pile
of dirt for a month" kinda smell to it.
Who
knows
Media Player has always had two major flaws that stopped me from using it.
- No support for ogg
- No support for listening to music in one player while watching random videos in another
Now that you can hack media player to play ogg, i figured, hey, I can bend the "no multiple players" rule with a little inventive coding.
What I ended up doing was embedding media player in my own component and controling the playlist myself. However, I figured that hey, while I was at it, I might as well do something I wished winamp could do, and make it a explorer toolbar. With some excellent help from CodeProject, doing all the hard work of wrapping the toolbar COM goo, I wasn't that hard to get my own player that sits quite nicely in my taskbar. Observe
Now all I have to do is make the custom playlist editor Not Suck© and i'll be ready to unleash to the other 5 people in the world who've wanted something like this.
Over the time that I've had metabuilders up, I've noticed one thing in particular that has always made me wonder about global community and human behavior.
I have many controls available on metabuilders. Some are more popular than others, understandably, but interest in them seems to come in waves. I'm defining "interest" by the number of downloads and number of emails I get about them. The big 3 are ComboBox, RowSelectorColumn, and DefaultButtons
It seems that if you graph each control's interest level over time, it will look like 3 sine waves, all out of phase with eachother.
I've often wonder how this works... I can't imagine that the general usefullness follows such curves, so I tend to conclude that their visibility in google or the varioius messageboards and lists follows this pattern... Maybe google will reindex my site so that a search for ComboBox is higher at some points than others... Perhaps people who answer lots of questions on messageboards with links to my site are more active during some times than others...
Maybe somebody who has seen and tracked this kind of behavior could enlighten me?
The built in DropDownList doesn't actually render any attributes you set for list items. This stops you from being able to set background colors and such, which people seem to like to do. Well, here's some code that will fix that.
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MetaBuilders.WebControls {
public class DDL : System.Web.UI.WebControls.DropDownList {
protected override void RenderContents(HtmlTextWriter writer) {
Boolean selectedItemRendered = false;
for (Int32 i = 0; (i < Items.Count); i++ ) {
ListItem litem = Items[i];
writer.WriteBeginTag("option");
if (litem.Selected) {
if (selectedItemRendered) {
throw new HttpException("DropDownList does not support multiple selection.");
}
selectedItemRendered = true;
writer.WriteAttribute("selected", "selected", false);
}
writer.WriteAttribute("value", litem.Value, true);
litem.Attributes.Render(writer);
writer.Write(">");
HttpUtility.HtmlEncode(litem.Text, writer);
writer.WriteEndTag("option");
writer.WriteLine();
}
}
}
}
MetaBuilders.com is at
the point where I need some public area for bugs/comments/etc.
Ideally, what I'd like
to have is some combination of bug tracking, forum, and
knowledgebase.
Has anybody seen such
a beast? Should I just use the forums
and have a specific Bugs forums?