Zapisywanie i odczytywanie obiektów

0

Witam drogich forumowiczów!

Siedzę w C# od jakiegoś roku i staram się rozgryźć windows forms. Większość rzeczy nie sprawia mi trudności poza zapisywaniem i odczytywaniem obiektów, a mianowicie chodzi i o taką sytuację:

mam mały programik, form który zawiera jeden button i flowlayoutpanel, gdy nacisnę button spawnuje taką oto klasę

 
public Class Txtbox
{
  Label lb = new Label();

  public void settings()
  { 
   //ustawienia czcionki i kolor, tekst dla labela
  }
} 

label dodawany jest to flowlayoutpanel i wszystko pięknie, tylko... jak sprawić żeby po zamknięciu programu i ponownym uruchomieniu flowlayoutpanel zachowywał wszystkie labele jakie stworzę?

próbowałem serializacji binary, ale wywalało mi błędy ".. is not marked as serializable", tak więc "leżę i kwiczę", byłbym dozgonnie wdzięczny gdyby ktoś powiedział mi jak to ugryźć!

Z góry dziękuję i liczę na wyrozumiałość.

1

Odpowiedź to serializacja. Wyrzuca ci błąd ponieważ klasa którą chcesz zserializować nie posiada atrybutu o tym, że może zostać zserializowana. W zależności od tego, jaki rodzaj serializacji chcesz użyć musisz dać odpowiedni atrybut do klasy. Np.

 
[Serializable]
class ASDFG
{
    public ASDFG()
   {
   }
}

Teraz klasa może zostać zserializowana

0

NeuroXiq dzięki za uwagę!

co do samego problemu to rozwiązanie chyba nie jest aż tak proste ponieważ po dodaniu [Serializable] nadal wyskakuje błąd "... is not marked as serializable"

2

Oczywiście oznaczyłeś tym atrybutem wszystkie klasy, które chcesz zapisać do pliku, oraz wszystkie inne klasy, z których te zapisywane korzystają?

0

somekind - wydaje mi się, że wszystko co potrzebne oznaczyłem, z resztą cały kod widać na załączniku. Błąd jest zawsze taki sam "formatter.Serialize(fileStream, ps); ... is not marked as serializable".

0

Czy Label, Padding i Size też są Serializable?

0

somekind

Po Twojej wypowiedzi wnioskuję, że robię jakiś oczywisty błąd, ale jako nowicjusz nie jestem w stanie go zauważyć? rozumiem, że Label,Padding i Size powinny zostać odpowiednio oznaczone? ale nie mam pojęcia w jaki sposób.

1

Atrybutem Serializable. Tylko to nie są chyba Twoje klasy, więc nie zrobisz tego, a porada @NeuroXiq jest nieadekwatna do Twojego problemu.

To co możesz zrobić, to zapisać konkretne wartości różnych właściwości swoich kontrolek. Żeby nie wymyślać własnego formatu pliku, możesz użyć tego, w czym wspomoże Cię Visual Studio: http://www.codeproject.com/Articles/15013/Windows-Forms-User-Settings-in-C

0

Powiem szczerze, że w takim wypadku to nie wiem co zrobić. Można by było bawić się w jakąś serializację do xml, która zapisywała by wszystkie pola klasy label, a potem poprzez jakąś metodę, robić to ręcznie przez parsowanie każdego pola w pliku do odpowiedniego pola w label. Z tym to trochę więcej by zabawy było ale może ktoś zna lepszy sposób.
Pozdr.

0

Dzięki chłopaki, jednak jak widać sprawa nie jest zbyt prosta i chyba przerasta to moje teraźniejsze możliwości programistyczne... muszę znaleźć jakąś alternatywę.

0

Nie serializuj wszystkich właściwości wszystkich obiektów, bo tego nie zrobisz. Zapisz sobie do jakiejś konfiguracji typy tych obiektów, ich położenie, rozmiar, treść, ewentualne itemy, kolor itp.

0

Postanowiłem zrezygnować z flowlayoutpanel i użyć listbox, ale znów mam problem, a mianowicie:

serializacja do pliku przebiega pomyślnie, ale nie mogę zrobić poprawnie deserializację tzn po włączeniu programu listbox jest pusty, mój kod wygląda następująco:


            if (File.Exists("textXML.xml"))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(ListBox.ObjectCollection));

                using (FileStream stream = File.OpenRead("textXML.xml"))
                {
                    ListBox.ObjectCollection obj = (ListBox.ObjectCollection)serializer.Deserialize(stream);
                    listBox1.Items.AddRange(obj);
                    
                }
            }
 
0

Co zwraca metoda Deserialize? IMHO null, bo klasa ListBox.ObjectCollection nie ma atrybutu Serializable, ale sprawdź. Pokaż też zawartość tego "testxml.xml" (dobra nazwa, dwa razy xml daje dwa razy większą pewność, że w środku będzie xml).
Jeśli już tak się uparłeś na serializację, to zrób ją na źródle danych listboksa.

0

ŁF

zawartość testxml:

<?xml version="1.0"?>
<ArrayOfAnyType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />  <anyType xsi:type="xsd:string"> 10-05-16 | wypoczynkowy | 3 | 17-05 / 19-05 / 2016 | </anyType>
  <anyType xsi:type="xsd:string"> 10-05-16 | wypoczynkowy | 1 | 24-05 / 24-05 / 2016 | </anyType>
</ArrayOfAnyType>

Jak na wstępie powiedziałem jestem nowicjuszem więc nie potrafię się połapać co i jak, dlatego też pytam.

0

To nie jest prawidłowy XML. Masz układ <arrayofanytype /><anytype/><anytype/></arrayofanytype>, powinieneś mieć <arrayofanytype><anytype/><anytype/></arrayofanytype>. XML musi mieć dokładnie jeden root i w nim całą zawartość. Dłubałeś w tym pliku i go rozwaliłeś.

0

ŁF zapewniam, że nie robiłem nic przy tym pliku, używam takiej metody do serializacji

 
            XmlSerializer serializer = new XmlSerializer(typeof(ListBox.ObjectCollection));

            using (FileStream stream = File.OpenWrite("textXML.xml"))
            {
                serializer.Serialize(stream, listBox1.Items);
            }

a gdybym całą zawartość listbox wrzucił do array'a i jego zapisywał oraz odczytywał?

2

Przy deserializacji leci Ci wyjątek "Could not deserialize global::System.Windows.Forms.ListBox.ObjectCollection. Parameterless constructor is required for collections and enumerators.", nie zauważyłeś go?

Tu masz piąte przez dziesiąte pokazane jak serializować/deserializować dane bezpośrednio z Items pod warunkiem znania ich typu.

			var serializer = new XmlSerializer(typeof(string[]));

			var sourceListBox = new ListBox();
			var destinationListBox = new ListBox();
			sourceListBox.Items.Add("item");

			using (var stream = new MemoryStream())
			{
				serializer.Serialize(stream, sourceListBox.Items.Cast<string>().ToArray()); // to jest kluczowy kawałek - drugi argument musi zwracać taki typ, dla jakiego został utworzony XmlSerializer

				stream.Position = 0;
				var deserializedItems = serializer.Deserialize(stream);
				destinationListBox.Items.AddRange((string[])deserializedItems);
			}
0

ŁF teraz już wszystko działa jak należy. Wielkie dzięki!

1 użytkowników online, w tym zalogowanych: 0, gości: 1