PS: If this functionality is widely use I would implement something like this. But it is only for less then 10 controls don't walk on this root.
As asp.net is extensible, we can extend Label, Textbox to have DefaultValues property and a mechanism to on and off (LoadDefaultValue which is true by default) the feature so that we can use it like ordinary controls.
- Implement's key feature is an interface called IXControl
- Which has three members. Namely string DefaultValues { get; set; }, bool LoadDefault { get; set; } and void Reset();
- All X Controls implement this interface.
- Inside the Reset method of each control, call common helper method called ResetProperties passing parameters, this control and DefaultValues property.
- DefaultValues propety should be a list of comma seperated { PropertyName=ProperyValue } pairs. Example DefaultValues="Text=DefaultText;ForeColor=Red;BackColor=Blue;Visible=false ... N
- Inside ResetProperties we decode DefaultValues string using string split and populate PropertyValue list
- Then use Reflection to go through each property of control and if propety name matchs one of in the list, set the value of the property using PropertyInfo
- Inside the panel Reset method, we call ResetInteranl so it will hock up all the child controls. Call Reset method using IXControl interface determining if the child type is IXControl.
- There is a catch, we need to go to children only if control is not a XPanel. Because once we call the Reset of XPanel it know how to reset all of it's children by itself
Code:
/// <summary> /// ControlManager and PropertyValue classes /// </summary> public class ControlManager { public static void ResetProperties(Control control, string defaultValues) { if (string.IsNullOrEmpty(defaultValues)) return; List<PropertyValue> pvs = new List<PropertyValue>(); foreach (string pv in defaultValues.Split(";".ToCharArray())) { string[] s = pv.Split("=".ToCharArray()); if (s.Length == 2 && !string.IsNullOrEmpty(s[0])) pvs.Add(new PropertyValue() { Property = s[0].Trim(), Value = s[1] }); } foreach (PropertyInfo p in control.GetType().GetProperties()) { PropertyValue pv = pvs.Find(x => x.Property.Equals(p.Name)); if (pv != null) { if (p.PropertyType.Equals(typeof(string))) p.SetValue(control, pv.Value, null); else if (p.PropertyType.Equals(typeof(Color))) { try { p.SetValue(control, new ColorConverter().ConvertFromString(pv.Value), null); } catch { } } else if (p.PropertyType.Equals(typeof(bool))) { bool value; if (bool.TryParse(pv.Value, out value)) p.SetValue(control, value, null); } /// /// You can extend this for any other criteria /// } } } } public class PropertyValue { public string Property { get; set; } public string Value { get; set; } } /// <summary> /// IXControl interface /// </summary> public interface IXControl { string DefaultValues { get; set; } bool LoadDefault { get; set; } void Reset(); } /// <summary> /// XLabel /// </summary> public class XLabel : Label, IXControl { public string DefaultValues { get; set; } public bool LoadDefault { get; set; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (this.LoadDefault && !this.Page.IsPostBack) this.Reset(); } public void Reset() { ControlManager.ResetProperties(this, this.DefaultValues); } } /// <summary> /// XTextbox /// </summary> public class XTextBox : TextBox, IXControl { public string DefaultValues { get; set; } public bool LoadDefault { get; set; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (this.LoadDefault && !this.Page.IsPostBack) this.Reset(); } public void Reset() { ControlManager.ResetProperties(this, this.DefaultValues); } } /// <summary> /// XPanel /// </summary> public class XPanel : Panel, IXControl { public string DefaultValues { get; set; } public bool LoadDefault { get; set; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (this.LoadDefault && !this.Page.IsPostBack) this.Reset(); } public void Reset() { ControlManager.ResetProperties(this, this.DefaultValues); this.ResetInternal(this.Controls); } private void ResetInternal(ControlCollection controlCollection) { foreach(Control control in controlCollection) { if (control is IXControl) ((IXControl)control).Reset(); if (control.Controls.Count > 0 && !control.GetType().Equals(typeof(XPanel))) this.ResetInternal(control.Controls); } } }
Markup:
<%@ Page Language="C#" AutoEventWireup="true" %> <%@ Register Assembly="Active.Web.UI.Controls" Namespace="Active.Web.UI.Controls" TagPrefix="active" %> <%@ Import Namespace="System.Drawing" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head2" runat="server"> <title>Reset Panel</title> <script runat="server"> protected override void OnInit(EventArgs e) { base.OnInit(e); for (int i = 0; i < 30; i++) { this.xpnlContainer.Controls.Add( new XLabel() { DefaultValues = String.Format("Text={0};Visible=true;ForeColor=Red", "Label " + i) }); this.xpnlContainer.Controls.Add( new XTextBox() { DefaultValues = String.Format("Text={0};Visible=true;BackColor=Blue", "Textbox " + i) }); XPanel panel =new XPanel() { BackColor = System.Drawing.Color.Red, Visible = false, DefaultValues = "Visible=true" }; panel.Controls.Add(new XLabel() { Text = "Nested Label - Init", DefaultValues = "Text=Nested Label Default" }); this.xpnlContainer.Controls.Add(panel); } } public void Reset(object sender, EventArgs e) { this.xpnlContainer.Reset(); } </script> </head> <body> <form id="form2" runat="server"> <div> <active:XPanel runat="server" ID="xpnlContainer" /> <asp:Button runat="server" ID="btnReset" Text="Reset" OnClick="Reset" /> <asp:Button runat="server" ID="btnPostback" Text="Postback" /> </div> </form> </body> </html>
No comments:
Post a Comment