E
Emil Stoev
Howdy eXperts!
I have this problem w/ my ASP.NET control. The control is a menu with the
following structure:
Menu
Group 1
Item 1
Item 2
Item 3
Group 2
Item 4
Item 5
etc...
What I want is to be able to add controls to any Item. I'm able to do that
but the state is lost and any events fired by those controls could not be
handled correctly.
Here's some of the code (stripped for simplicity):
[assembly:TagPrefix("Menu123.WebControls", "Menu123")]
namespace Menu123.WebControls
{
internal class MyMenuBuilder : ControlBuilder
{
public override bool AllowWhitespaceLiterals()
{
return false;
}
public override Type GetChildControlType(string tagName, IDictionary
attribs)
{
if (tagName.ToLower() == "MyMenugroup" || tagName.ToLower() ==
"Menu123:MyMenugroup")
{
return typeof(MyMenuGroupControl);
}
return null;
}
}
[ToolboxData("<{0}:MyMenu id=MyMenu1 runat=server></{0}:MyMenu>")]
[Designer("Menu123.WebControls.MyMenuDesigner")]
[ControlBuilderAttribute(typeof(MyMenuBuilder))]
[ParseChildren(false)]
public class MyMenu : WebControl, IPostBackEventHandler, INamingContainer
{
private ArrayList _MenuStructure = new ArrayList();
[Browsable(false)]
public ArrayList MenuStructure
{
get
{
return _MenuStructure;
}
set
{
_MenuStructure = value;
}
}
protected override void AddParsedSubObject(object obj)
{
if (obj is MyMenuGroupControl)
{
MenuStructure.Add(obj);
}
}
protected override void Render(HtmlTextWriter output)
{
foreach (MyMenuGroupControl _group in MenuStructure)
{
// Render the group
foreach (MyMenuItemControl _item in _group.GroupStructure)
{
// Render the items
// Render the nested controls here !!! (e.g. add them to table cell,
etc)
}
}
}
protected override object SaveViewState()
{
object baseState = base.SaveViewState();
object[] state = new object[2];
state[0] = (baseState != null) ? baseState : null;
if (MenuStructure != null && MenuStructure.Count > 0)
{
state[1] = new object[MenuStructure.Count];
for (int i = 0; i < MenuStructure.Count; i++)
{
object[] g_state = new object[2];
if (_group.GroupStructure != null && _group.GroupStructure.Count > 0)
{
g_state[0] = new object[_group.GroupStructure.Count];
for (int n = 0; n < _group.GroupStructure.Count; n++)
{
object[] i_state = null;
MyMenuItemControl _item =
(MyMenuItemControl)_group.GroupStructure[n];
if (_item != null)
{
i_state = new object[1];
i_state[0] = _item.Label;
((object[])g_state[0])[n] = i_state;
}
}
}
g_state[1] = _group.Label;
((object[])state[1]) = g_state;
}
}
return state;
}
protected override void LoadViewState(object savedState)
{
if (savedState != null)
{
object[] state = (object[])savedState;
base.LoadViewState(state[0]);
if (state[1] != null)
{
MenuStructure.Clear();
foreach (object[] g_state in (object[])state[1])
{
if (g_state == null) continue;
MyMenuGroupControl _group = new MyMenuGroupControl();
if (g_state[0] != null)
{
foreach (object[] i_state in (object[])g_state[0])
{
if (i_state == null) continue;
MyMenuItemControl _item = new MyMenuItemControl();
_item.Label = (string)i_state[0];
_group.GroupStructure.Add(_item);
}
}
_group.Label = (string)g_state[1];
MenuStructure.Add(_group);
}
}
}
}
}
[System.ComponentModel.ToolboxItem(false)]
internal class MyMenuGroupBuilder : ControlBuilder
{
public override bool AllowWhitespaceLiterals()
{
return false;
}
public override Type GetChildControlType(string tagName, IDictionary
attribs)
{
if (tagName.ToLower() == "MyMenuitem" || tagName.ToLower() ==
"Menu123:MyMenuitem")
{
return typeof(MyMenuItemControl);
}
return null;
}
}
[ControlBuilderAttribute(typeof(MyMenuGroupBuilder))]
[System.ComponentModel.ToolboxItem(false)]
[ParseChildren(false)]
public class MyMenuGroupControl : WebControl
{
public MyMenuGroupControl() {}
protected override void AddParsedSubObject(object obj)
{
if (obj is MyMenuItemControl)
{
GroupStructure.Add(obj);
}
}
private ArrayList _GroupStructure = new ArrayList();
/// <summary>
/// Use this container to programaticaly add Items in the group.
/// </summary>
[Browsable(false)]
public ArrayList GroupStructure
{
get { return _GroupStructure; }
set { _GroupStructure = value; }
}
private string _Label;
/// <summary>
/// Use this property to specify the group label.
/// </summary>
public string Label
{
get { return _Label; }
set { _Label = value; }
}
}
[System.ComponentModel.ToolboxItem(false)]
[ParseChildren(true, "ItemTemplate")]
[PersistChildren(false)]
public class MyMenuItemControl : WebControl, INamingContainer
{
public MyMenuItemControl()
{
_ItemTemplate = new ControlCollection(this);
}
private ControlCollection _ItemTemplate;
[NotifyParentProperty(true)]
[PersistenceMode(PersistenceMode.InnerProperty) ]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ControlCollection ItemTemplate
{
get { return _ItemTemplate; }
}
private string _Label;
/// <summary>
/// Use this property to specify the item label.
/// </summary>
public string Label
{
get { return _Label; }
set { _Label = value; }
}
}
}
I have this problem w/ my ASP.NET control. The control is a menu with the
following structure:
Menu
Group 1
Item 1
Item 2
Item 3
Group 2
Item 4
Item 5
etc...
What I want is to be able to add controls to any Item. I'm able to do that
but the state is lost and any events fired by those controls could not be
handled correctly.
Here's some of the code (stripped for simplicity):
[assembly:TagPrefix("Menu123.WebControls", "Menu123")]
namespace Menu123.WebControls
{
internal class MyMenuBuilder : ControlBuilder
{
public override bool AllowWhitespaceLiterals()
{
return false;
}
public override Type GetChildControlType(string tagName, IDictionary
attribs)
{
if (tagName.ToLower() == "MyMenugroup" || tagName.ToLower() ==
"Menu123:MyMenugroup")
{
return typeof(MyMenuGroupControl);
}
return null;
}
}
[ToolboxData("<{0}:MyMenu id=MyMenu1 runat=server></{0}:MyMenu>")]
[Designer("Menu123.WebControls.MyMenuDesigner")]
[ControlBuilderAttribute(typeof(MyMenuBuilder))]
[ParseChildren(false)]
public class MyMenu : WebControl, IPostBackEventHandler, INamingContainer
{
private ArrayList _MenuStructure = new ArrayList();
[Browsable(false)]
public ArrayList MenuStructure
{
get
{
return _MenuStructure;
}
set
{
_MenuStructure = value;
}
}
protected override void AddParsedSubObject(object obj)
{
if (obj is MyMenuGroupControl)
{
MenuStructure.Add(obj);
}
}
protected override void Render(HtmlTextWriter output)
{
foreach (MyMenuGroupControl _group in MenuStructure)
{
// Render the group
foreach (MyMenuItemControl _item in _group.GroupStructure)
{
// Render the items
// Render the nested controls here !!! (e.g. add them to table cell,
etc)
}
}
}
protected override object SaveViewState()
{
object baseState = base.SaveViewState();
object[] state = new object[2];
state[0] = (baseState != null) ? baseState : null;
if (MenuStructure != null && MenuStructure.Count > 0)
{
state[1] = new object[MenuStructure.Count];
for (int i = 0; i < MenuStructure.Count; i++)
{
object[] g_state = new object[2];
if (_group.GroupStructure != null && _group.GroupStructure.Count > 0)
{
g_state[0] = new object[_group.GroupStructure.Count];
for (int n = 0; n < _group.GroupStructure.Count; n++)
{
object[] i_state = null;
MyMenuItemControl _item =
(MyMenuItemControl)_group.GroupStructure[n];
if (_item != null)
{
i_state = new object[1];
i_state[0] = _item.Label;
((object[])g_state[0])[n] = i_state;
}
}
}
g_state[1] = _group.Label;
((object[])state[1]) = g_state;
}
}
return state;
}
protected override void LoadViewState(object savedState)
{
if (savedState != null)
{
object[] state = (object[])savedState;
base.LoadViewState(state[0]);
if (state[1] != null)
{
MenuStructure.Clear();
foreach (object[] g_state in (object[])state[1])
{
if (g_state == null) continue;
MyMenuGroupControl _group = new MyMenuGroupControl();
if (g_state[0] != null)
{
foreach (object[] i_state in (object[])g_state[0])
{
if (i_state == null) continue;
MyMenuItemControl _item = new MyMenuItemControl();
_item.Label = (string)i_state[0];
_group.GroupStructure.Add(_item);
}
}
_group.Label = (string)g_state[1];
MenuStructure.Add(_group);
}
}
}
}
}
[System.ComponentModel.ToolboxItem(false)]
internal class MyMenuGroupBuilder : ControlBuilder
{
public override bool AllowWhitespaceLiterals()
{
return false;
}
public override Type GetChildControlType(string tagName, IDictionary
attribs)
{
if (tagName.ToLower() == "MyMenuitem" || tagName.ToLower() ==
"Menu123:MyMenuitem")
{
return typeof(MyMenuItemControl);
}
return null;
}
}
[ControlBuilderAttribute(typeof(MyMenuGroupBuilder))]
[System.ComponentModel.ToolboxItem(false)]
[ParseChildren(false)]
public class MyMenuGroupControl : WebControl
{
public MyMenuGroupControl() {}
protected override void AddParsedSubObject(object obj)
{
if (obj is MyMenuItemControl)
{
GroupStructure.Add(obj);
}
}
private ArrayList _GroupStructure = new ArrayList();
/// <summary>
/// Use this container to programaticaly add Items in the group.
/// </summary>
[Browsable(false)]
public ArrayList GroupStructure
{
get { return _GroupStructure; }
set { _GroupStructure = value; }
}
private string _Label;
/// <summary>
/// Use this property to specify the group label.
/// </summary>
public string Label
{
get { return _Label; }
set { _Label = value; }
}
}
[System.ComponentModel.ToolboxItem(false)]
[ParseChildren(true, "ItemTemplate")]
[PersistChildren(false)]
public class MyMenuItemControl : WebControl, INamingContainer
{
public MyMenuItemControl()
{
_ItemTemplate = new ControlCollection(this);
}
private ControlCollection _ItemTemplate;
[NotifyParentProperty(true)]
[PersistenceMode(PersistenceMode.InnerProperty) ]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ControlCollection ItemTemplate
{
get { return _ItemTemplate; }
}
private string _Label;
/// <summary>
/// Use this property to specify the item label.
/// </summary>
public string Label
{
get { return _Label; }
set { _Label = value; }
}
}
}