Steuerelement-Array's serialisieren und DataBinding
Frank Dzaebel, erstellt am: 2.8.2008, zuletzt geändert:
2.8.2008
Kategorie: Windows Forms, .NET-Version: 2.0,
[Download]
Will man Steuerelemente automatisch serialisieren, so kann man dies z.B. über ihren Namen erreichen. Hier werden die typsicheren
Properties.Settings zur Serialisierung
benutzt. Dabei wird eine List<TextBox>
Klasse benutzt, die über IXmlSerializable in der Lage ist, die Controls
mit einer vorher definierten Anzahl an Eigenschaften, in die BenutzerSettings zu
serialisieren. Die Änderungen an den TextBox-Inhalten des Benutzers, werden automatisch
gesichert. Dies passiert über DataBindings und BindingSource.
Für .NET 1.1 siehe auch
hier.

#region usings ...
#endregion
namespace TwoLineBinding
{
/// <summary>http://Dzaebel.NET/TwoLineBinding.htm
/// [Download mit DataBindings] </summary>
public class Form1 : System.Windows.Forms.Form
{
TextBoxen autoTbs = new TextBoxen();
TextBoxen manuTbs = new TextBoxen();
Properties.Settings Props = Properties.Settings.Default;
TextBoxen propAuto, propManu;
enum Felder { Automatisch, Manuell }
private void Form1_Load(object sender, System.EventArgs e)
{
InitControls(this);
propAuto = Props.TextfelderAuto;
propManu = Props.TextfelderManu;
SetDataBindingProps(propAuto, autoTbs);
SetDataBindingProps(propManu, manuTbs);
}
private void SetDataBindingProps(TextBoxen propTextBoxen, TextBoxen formTextBoxen)
{
if (propTextBoxen == null) propTextBoxen = formTextBoxen;
BindingSource bs = new BindingSource(propTextBoxen, null);
for (int i = 0; i < formTextBoxen.Count; i++)
formTextBoxen[i].DataBindings.Add("Text", bs[i], "Text");
}
#region InitControls
private void InitControls(Control control)
{
foreach (Control ctl in control.Controls)
{
if (ctl.Controls.Count > 0) InitControls(ctl);
TextBox tb = ctl as TextBox;
if (tb != null)
{
if (tb.Name.EndsWith("a")) manuTbs.Add(tb);
if (!tb.Name.EndsWith("a")) autoTbs.Add(tb);
}
}
}
#endregion
#region Vom Windows Form-Designer generierter Code . . .
#endregion
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Props.Save();
}
}
public class TextBoxen : List<TextBox>, IXmlSerializable
{
PropertyDescriptorCollection eigenschaftenZuSerialisieren =
new PropertyDescriptorCollection(new PropertyDescriptor[] {});
string[] propsToSerialize = new string[] { "Text", "Name" };
public TextBoxen()
{
List<string> propList = new List<string>(propsToSerialize);
PropertyDescriptorCollection pdcControl =
TypeDescriptor.GetProperties(typeof(TextBox));
foreach (PropertyDescriptor pd in pdcControl)
if (propList.Contains(pd.Name))
eigenschaftenZuSerialisieren.Add(pd);
}
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader)
{
string name = "ungesetzt";
object o = new Control();
try
{
while (reader.Read())
{
if (reader.Name == "ChangeCollection" &&
reader.NodeType == XmlNodeType.EndElement)
{
break;
}
string typeName = reader.Name;
if (typeName != "Control") break;
string val = reader.ReadElementString();
o = FindControl(Application.OpenForms[0], val);
name = reader.Name;
val = reader.ReadElementString();
while (name != "")
{
PropertyDescriptor pd = eigenschaftenZuSerialisieren[name];
object v = pd.Converter.ConvertFromInvariantString(val);
pd.SetValue(o, v);
name = reader.Name;
if (name == "Control" &&
reader.NodeType == XmlNodeType.EndElement)
{
this.Add((TextBox)o); break;
}
val = reader.ReadElementString();
}
}
}
catch (Exception exp) { Fehlermeldung((Control)o, exp, name); }
}
Control FindControl(Control control, string controlName)
{
if (control.Name == controlName) return control;
foreach (Control ctl in control.Controls)
{
if (ctl.Name == controlName) return ctl;
if (ctl.Controls.Count > 0)
{
Control c = FindControl(ctl, controlName);
if (c != null) return c;
}
}
return null;
}
public void WriteXml(XmlWriter writer)
{
foreach (Control ctl in this)
{
string name = "ungesetzt";
try
{
if (!(ctl is TextBox)) continue;
writer.WriteStartElement("Control");
writer.WriteElementString("Name", ctl.Name);
foreach (PropertyDescriptor pd in eigenschaftenZuSerialisieren)
{
if ((pd.PropertyType.IsValueType || pd.PropertyType == typeof(string)) &&
pd.PropertyType != typeof(IntPtr) && !pd.IsReadOnly && pd.Name != "Name")
{
writer.WriteStartElement(pd.Name);
object val = pd.GetValue(ctl);
string v = pd.Converter.ConvertToInvariantString(val);
writer.WriteString(v); writer.WriteEndElement();
Debug.WriteLine(pd.Name + " = " + v);
}
}
writer.WriteFullEndElement();
}
catch (Exception exp) { Fehlermeldung(ctl, exp, name); }
}
}
void Fehlermeldung(Control ctl, Exception exp, string propertyName)
{
MessageBox.Show(exp.Message + "\r\nControl:" + ctl.Name +
", Eigenschaft:" + propertyName);
}
}
}