Controls to dump key/value pairs
This bit is a little too much to digest:


this.Controls.Add(new Xml {
    DocumentContent = new XElement("keys",
                            from key in this.Keys
                            select new XElement("key",
                                        new XAttribute("name", key),
                                        this[key])).ToString(),
    TransformSource = DumpKeyValuePairs.XsltPath,
});



The trailing comma is annoying, but the LINQ query syntax is a little bit overboard. The instruction is doing too many things.

Wouldn't this be clearer?

Controls.Add(xml);


There's no need to qualify XsltPath with the DumpKeyValuePairs type, even if the field is static - you're in the same type anyway. Actually, this:


static string XsltPath = "~/Controls/DumpKeys.xslt";



Should really be this:

private static readonly string XsltPath = "~/Controls/DumpKeys.xslt";


Now, in order to turn that LINQ jam into a simple Controls.Add(xml); instruction, things need to happen.

var xml = new Xml 
{ 
    DocumentContent = CreateDocumentContent(),
    TransformSource = XsltPath
};


The CreateDocumentContent() method could be where that LINQ query lives.

private string CreateDocumentContent()
{
    return new XElement("keys", Keys.Select(CreateKeyElement)).ToString();
}


And that CreateKeyElement method group, extracted to its own one-liner method again, makes it pretty clear what's going on:

private XElement CreateKeyElement(string key)
{
    return new XElement("key", new XAttribute("name", key), this[key]);
}


Cramming all these functions into a single instruction is making maintenance much harder than it needs to be.




abstract protected string this[string index] { get; }



Maybe it's just me, but in my mind an index is an int that specifies the position of an item in a collection. What you really have here is a string name for accessing the values in some dictionary; correctly naming the indexer parameter can avoid confusion here.