C# [UWP] Objekt oder List<Objekt> als Datei oder in LocalSettings speichern

agredo

Cadet 2nd Year
Registriert
Juni 2015
Beiträge
24
Guten Tag Community.
Ich stehe momentan vor einem Problem. Ich möchte eine handschriftliche Notiz, welche ich in einer Win10 Universal App mittels der InkCanvas eingebe, speichern.

Die Datei aysnchron als Datei zu speichern und zu laden ist nicht das Problem.

Ich habe eine Klasse Cards, die mir die Notiz speichern soll. Und eine Klasse Stack, die mehrere Cards als Liste speichert.
Die Stack-Objekte die jeweils die Cards enthalten werden in einer Liste gespeichert. Nun möchte ich diese Liste Speichern.

Das Problem ist, dass ich keinen Weg finde dieses Objekt zu serialisieren oder in LocalSettings zu speichern.

Ich habe einen Weg gefunden, der über eine JASON Bibliothek führt, dort kommt es aber zu einem Loop bei der Canvas.

"Self referencing loop detected for property 'InkPresenter' with type 'Windows.UI.Input.Inking.InkPresenter'. Path '[0].Cards[0].InkCanvas.InkPresenter.StrokeInput'"

In der Zeile

string val = JsonConvert.SerializeObject(value);

Eine zweite Sache ist:

Wenn ich die InkCanvas bemale diese dann nach einem Button_Click in einem InkCanvas-Objekt speichere, die Canvas leere und darauf, nach einem anderen Button_Click, der InkCanvas, das erstellte InkCanvas-Objekt übergebe, erhalte ich nicht meine Notiz zurück. Selbiges gilt auch für den InkPresenter und dem StrokeContainer.

Was mache ich da Falsch?

Vielen Dank

Agredo

Code:
public class Stack
    {
        public string Name { get; set; }

        public List<Card> Cards { get; set; }

        public Stack()
        {
            Cards = new List<Card>();
        }
        public Stack(string Name)
        {
            Cards = new List<Card>();

            this.Name = Name;
        }

        public static void SaveStacks(List<Stack> Stacks)
        {
            //Lokales Speichern der Liste
            Stack.SaveStack("myStacks", Stacks);

        }

        public void addCard(InkCanvas myCanvas)
        {
            Cards.Add(new Card(myCanvas));
        }

        public static T GetStack<T>(string name)
        {
            var localSettings = ApplicationData.Current.LocalSettings;
            if (localSettings.Values.ContainsKey(name) && localSettings.Values.ContainsKey(name + "Type"))
            {
                var type = Type.GetType((string)localSettings.Values[name + "Type"]);
                var val = (string)localSettings.Values[name];

                if (type == null || val == null)
                    return default(T);
                else
                    return (T)JsonConvert.DeserializeObject(val, type);
            }
            else
                return default(T);
        }

        public static bool SaveStack(string name, object value)
        {
            string val = JsonConvert.SerializeObject(value);
            Type type;

            if (value != null)
                type = value.GetType();
            else
                return false;

            var localSettings = ApplicationData.Current.LocalSettings;
            if (localSettings.Values.ContainsKey(name))
            {

                localSettings.Values[name + "Type"] = type.AssemblyQualifiedName;
                localSettings.Values[name] = val;
            }
            else
            {
                localSettings.Values.Add(name, val);
                localSettings.Values.Add(name + "Type", type.AssemblyQualifiedName);
            }

            return true;
        }
    }

Code:
public class Card
    {
        public InkCanvas InkCanvas { get; set; }

        public Card(InkCanvas myInkCanvas)
        {
            InkCanvas = myInkCanvas;
        }

        public Card()
        {

        }

    }
 
Dein Problem ist, wenn ich es richtig verstehe, dass du die Klasse Stack Serializieren möchtest. Diese enthält aber den Unbekannten Typ Card. Dazu kannst du dich in dem Artikel auf CodeProject schlau machen.

Alternativ möchtest du eigentlich nur die Strokes deiner InkCanvas speichern, und der StrokeContainer bietet dir mit SaveAsync und LoadAsync entsprechende Möglichkeiten. Auch dazu gibt es ein Beispiel.

Grundsätzlich als Tipp für die Zukunft, immer nur das Speichern, was du auch wirklich haben möchtest. Die komplette InkCanvas zu speichern ist kein ordentlicher Weg. Man könnte noch weiter ausschlagen, aber schätze mal du bist noch am Anfang, da kommt in Zukunft dann noch so einiges :). Beste Grüße und Viel Spaß beim Programmieren...
 
Füg mal in deiner Klasse das ein:

[DataContract(IsReference = true)]
public class Card {

Und dann für jede zu speicherende Variable [DataMember]

DAtaContracts kenne ich zwar für System.Runtime.Serialization zur ÜBertragung übers Internet, aber zumindest deine Fehlermeldung hatte ich auch konnte ich mit dem "IsReference = True" lösen
 
Ich Danke euch beiden, aber es beides nicht geholfen.

@PapstRatze

Ich habe die Strokes bereits in einer Datei mittels LoadAsync() und SaveAsync() geladen und gespeichert. Nur Muss ich diese Dateien wieder in für jeden Stack Laden. Das habe ich durch eine Ordnerstruktur ( StackName \ Ink1Front.ink, Ink1Back.ink, Ink1Header.txt, Ink2Front.ink,Ink2Back.ink, Ink2Header.txt, .... Ink(n)Front.ink, Ink(n)Back.ink, Ink(n)Header.txt,) gelöst. Da dieses sehr umständlich wurde, wollte ich halt die Stacks oder eine Liste aus Stacks serialisieren.

Dass ich die InkCanvas gespeichert habe war nur ein Versuch. :D Ich habe es nicht hinbekommen die InkCanvas ohne die Strokes in einer Datei zu speichern wieder zu Laden.

Ich habe den Weg in deinem Link versucht zu Folgen, bin aber dann, bei den Assamblies gescheitert, da das Objekt Type nicht die selben Properties und Methoden hat, wie in dem Beispiel. Das wird vermutlich daran liegen, dass ich keine WPF sondern eine UWP entwickel.

@KeepXtreme
Dein Weg habe ich natürlich auch Probiert, aber das hat leider auch nicht geklappt.

Gibt es denn eventuell noch andere Möglichkeiten, eine Solche unübersichtliche Ordnerstruktur zu vermeiden?

Vielen Dank für eure Antworten :)
 
Zurück
Oben