Frage von Pierre1994, 27

Wie serialisiere ich das in C#?

Hallo ja wie oben beschrieben bräuchte ich eure Hilfe bei einer Frage zu meinem C# Projekt ich möchte gerne speichern können in meinem Programm. Auf dem Bild seht ihr was ich meine. 1. Es soll auf den Hinzufügen Button gedrückt werden 2.dadurch werden 3 Labels und 2 TrackBars hinzugefügt zum Schluss soll man auf Speichern drücken können und nachdem man das Programm geschlossen und wieder geöffnet hat sollen die vorher hinzugefügten Elemente immer noch da sein.

Antwort
von CrystalixXx, 19

Da gibt es verschiedene Möglichkeiten.

1. Anwendungseinstellungen. Du nutzt die Funktion von Visual Studio, die solche Einstellungen automatisch speichert und lädt. Dabei könntest du die Steuerelemente im Designer anlegen und die Visible-Eigenschaft auf False setzen. Bei "Hinzufügen" wird die Eigenschaft lediglich auf True festgelegt, was es dir ermöglicht die Visible-Eigenschaft über die Anwendungseinstellungen automatisch speichern/laden zu lassen.

2. Manuell. Du übernimmst das Speichern selbst und kannst dabei alles selbst individuell festlegen. Dadurch gibt es zig Möglichkeiten. Du kannst dir dein eigenes Datenformat festlegen, ober du wählst ein vorhandenes: Klartext, Schlüssel-Wert-Paare, XML, binär, oder oder oder. Es kommt hierbei drauf an, was du alles speichern willst. Wenn die Positionen und Werte immer gleich bleiben, dann reicht ein einzelnes Flag, was angibt, ob auf "Hinzufügen" gedrückt wurde (analog zu Punkt 1 mit der Visible-Eigenschaft). Oder du speicherst außerdem den Text respektive Wert ab, die Position, die Farben und so weiter.

Das ist eben davon abhängig, was du alles speichern willst. Das musst du aber selbst abwägen.

Kommentar von Pierre1994 ,

Für mich wäre denke ich die 2. Methode am besten aber wie geh ich da am besten ran also es sind nicht immer dieselben Koordinaten sondern man kann bis zu 10 solcher "Pakete" wie ich sie in dem Bild rot markiert habe hinzufügen muss ich dann die Methode die durch den Button Hinzufügen aufgerufen wird serialisieren oder wie geht das stehe ganz schön auf dem Schlauch ^^

Kommentar von CrystalixXx ,

Am besten du schreibst dir eine Klasse, die die Daten für ein Steuerelement bereithält (Text, Position, etc.) und eine Klasse, die diese Daten beinhaltet und speichern und laden kann.

Ich habe auf die Schnelle mal etwas zusammen geschrieben. Die nachfolgende Klasse ist jene, die die einzelnen Daten zu einem Steuerelement enthält. Das ist zum einen der Typ (der vollständige Name des Steuerelementes, z. B. System.Windows.Forms.Button), die Position und der anzuzeigende Text.

[Serializable()]
public class ControlSetting
{
public ControlSetting(string type, Point location, string text)
{
_Type = type;
_Location = location;
_Text = text;
}

private string _Type;
public string Type
{
get { return _Type; }
set { _Type = value; }
}

private Point _Location;
public Point Location
{
get { return _Location; }
set { _Location = value; }
}

private string _Text;
public string Text
{
get { return _Text; }
set { _Text = value; }
}
}

Dann die Klasse, die die einzelnen Einstellungen verwaltet. Sie enthält außerdem das Speichern und Laden von Einstellungen und löst bei Erfolg ein Ereignis aus (das brauchst du gleich noch).

public class ControlSettings
{
public event SavedEventHandler Saved;
public delegate void SavedEventHandler(object sender, System.EventArgs e);
public event LoadedEventHandler Loaded;
public delegate void LoadedEventHandler(object sender, System.EventArgs e);

public ControlSettings()
{
_List = new List();
}

private List _List;
public List List
{
get { return _List; }
}

public void Save(string file)
{
using (Stream fs = new FileStream(file, FileMode.OpenOrCreate))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, this.List);
OnSaved(System.EventArgs.Empty);
}
}

public void Load(string file)
{
if (!File.Exists(file))
throw new FileNotFoundException("Datei nicht gefunden.");

using (Stream fs = new FileStream(file, FileMode.OpenOrCreate))
{
BinaryFormatter bf = new BinaryFormatter();
_List = (List)bf.Deserialize(fs);
OnLoaded(System.EventArgs.Empty);
}
}

protected void OnSaved(System.EventArgs e)
{
if (Saved != null)
Saved(this, e);
}

protected void OnLoaded(System.EventArgs e)
{
if (Loaded != null)
Loaded(this, e);
}

}

Jetzt fehlt nur noch der Code, der in dein Formular gehört.

public partial class Form2 : Form
{
private ControlSettings s = new ControlSettings();

public Form2()
{
InitializeComponent();

s.Saved += s_Saved;
s.Loaded += s_Loaded;
}

private void Button1_Click(System.Object sender, System.EventArgs e)
{
s.List.Add(new ControlSetting("System.Windows.Forms.Button", new Point(30, 30), "Hallo"));
s.Save("D:\\Test.bin");
}

private void Button2_Click(System.Object sender, System.EventArgs e)
{
s.Load("D:\\Test.bin");
}

private void s_Loaded(object sender, System.EventArgs e)
{
foreach (ControlSetting item in s.List)
{
Type t = Type.GetType(item.Type + ", System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", true, true);
Control c = (Control)Activator.CreateInstance(t);
c.Location = item.Location;
c.Text = item.Text;
c.Visible = true;
this.Controls.Add(c);
}

MessageBox.Show("Einstellungen geladen.");
}

private void s_Saved(object sender, System.EventArgs e)
{
MessageBox.Show("Einstellungen gespeichert.");
}
}

Der Code für das Formular ist jetzt nur zum Testen, den solltest du dann entsprechend deiner Zwecke anpassen. Im Button1_Click habe ich testweise eine Einstellung erzeugt und der Liste hinzugefügt. Es soll ein Button bei x=30, y=30 mit dem Text "Hallo" erstellt werden, wenn die Einstellungen geladen werden.

Dazu ist jetzt das Ereignis "Loaded" wichtig. Denn darauf solltest du reagieren, wenn die Einstellungen geladen wurden, damit du die Steuerelemente anzeigen kannst. Dort wird zunächst der Type des gewollten Steuerelementes erzeugt und davon eine Instanz erstellt. Eigenschaften zuweisen und das Steuerelement hinzufügen - Fertig.

Sieht vielleicht recht kompliziert aus, ist aber eigentlich relativ einfach.

Kommentar von CrystalixXx ,

PS: Das Erzeugen des Types anhand des hinterlegten Strings ist in meinem Code-Beispiel nicht gut gelöst, weil der vollständige Assembly-Name fest hinterlegt ist. Für eine andere Framework-Version könnte das Probleme verursachen. Besser man schreibt eine Methode, die die referenzierte System.Windows.Forms-Assembly zurückgibt. Alle referenzierten Assemblys könnte man mit folgender Zeile ermitteln:

System.Reflection.Assembly.GetExecutingAssembly().GetReferencedAssemblies

Keine passende Antwort gefunden?

Fragen Sie die Community