none
"OpenFileDialog.FileName" wird nicht serialisiert RRS feed

  • Frage

  • Hallo,

    für eine Anwendung habe ich ein UserControl erstellt, da ein UserControl nicht Serialisierbar ist habe ich das ISerializable Interface implementiert. Bzw. versucht zu implementieren, denn eine der Eigenschaften ist ein FileName-string welches von einem OpenFileDialog kommt, wenn diese Eigenschaft aber nicht "Empty" ist, wird sie auch nicht serialisiert. Weiss jemand woran das liegen kann?

    Hier mein Code:

     

     

     

    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
    
            public void GetObjectData(SerializationInfo info, StreamingContext context)
    
            {
    
                info.AddValue("name", tbName.Text);
    
                //info.AddValue("source", tbSource.Text);
    
                //info.AddValue("source", file.FileName);
    
                info.AddValue("source", fileName);
    
                info.AddValue("cbloop", cbLoop.IsChecked);
    
                info.AddValue("cbcmdoff", cbCmdOff.IsChecked);
    
                info.AddValue("cbtimer", cbTime.IsChecked);
    
                info.AddValue("durationtext", tbDuration.Text);
    
                info.AddValue("duration", duration);
    
                info.AddValue("volume", sldVolume.Value);
    
                info.AddValue("cmdon", tbCmdOn.Text);
    
                info.AddValue("cmdoff", tbCmdOff.Text);
    
            }
    

    wobei in dieser Version ein public string fileName erstellt wurde welcher einen default-Wert hat und erst beschrieben wird wenn der User explizit ein File auswählt (FileOK-Event).

    Der Initialwert wird serialisiert, wenn der string aber überschrieben wurde, nicht mehr. Auch wenn der gleiche wert (Text) beim Debuggen drinsteht liefert die Equals(string)-Methode false. Liegt es an den Backslashes? Die werden zwar bei MouseOver angezeigt wenn man auf das FileName-Attribut geht, aber nicht bei der OpenFileDialog-Instanz (bzw. sender im FileOk-Event).



    • Bearbeitet eutrom Donnerstag, 15. Dezember 2011 09:55
    Donnerstag, 15. Dezember 2011 09:30

Antworten

  • Hallo,

    aus Deinem Code kann man nicht entnehmen, wo und wie fileName gesetzt wird,
    so dass eine direkte Aussage schwierig ist.

    Im allgemeinen sollte man aber Steuerelemente nicht serialisieren.
    Verlagere die Informationen in eine eigenständige Klasse, in der Du die zu persistierenden Werte unterbringst.

    Eine mögliche Variante hatte ich gezeigt in: UserControl Werte an Form übergeben....
    Dort waren es mehrere Formulare, aber vom Prinzip kann man das dortige Konzept für jeden Zweck verwenden
    und die Datenbindung ebenso einsetzen.

    Reicht Dir eine binäre Serialisierung müsstest Du die Klasse nur als Serializable kennzeichnen.
    Alternativ kannst Du aber auch die Xml Serialisierung verwenden.

    Eine weitere Möglichkeit wäre die Werte als Anwendungseinstellungen (je Benutzer) zu speichern.

    Gruß Elmar

    • Als Antwort markiert eutrom Donnerstag, 15. Dezember 2011 13:41
    Donnerstag, 15. Dezember 2011 10:52
  • Das ist C#??? ;)

    Spaß beiseite, habs nicht böse gemeint aber wenn ich manche Foren so lese stehen da lauter unnütze Antworten wie "Du musst schon genauer schreiben was du machen willst" oder "Wir können ja gar nicht wissen was du für ein System hast" obwohl es gar nichts mit dem Problem an sich zu tun hat, und am Ende ist überhaupt keine richtige Antwort da.

    Hab das tatsächliche Problem lokalisiert:

    Da ich will dass die Serialisierungsdatei im gleichen Verzeichnis landet in dem auch die fertige Anwendung liegt habe ich keinen Pfad angegeben sondern nur den Dateinamen:

    FileStream stream = new FileStream("config.txt", FileMode.Create);

    In diesem Fall scheint die FileStream-Klasse den Pfad durch Environment.CurrentDirectory zu ermitteln. Nachdem aber das OpenFileDialog offen war ändert sich die Eigenschaft CurrentDirectory, die Datei wird also dorthin geschrieben wo sich die zuletzt geöffnete Datei befindet. Geladen wird es aber beim Start natürlich wieder aus dem Verzeichnis wo die Anwendung ist.

    Habe es also nun in  FileStream stream = new FileStream(AppDomain.CurrentDomain.BaseDirectory +"config.txt", FileMode.Create); gändert und es funktioniert.

     


    • Bearbeitet eutrom Donnerstag, 15. Dezember 2011 13:28
    • Als Antwort markiert eutrom Donnerstag, 15. Dezember 2011 13:41
    Donnerstag, 15. Dezember 2011 13:23

Alle Antworten

  • Hallo,

    aus Deinem Code kann man nicht entnehmen, wo und wie fileName gesetzt wird,
    so dass eine direkte Aussage schwierig ist.

    Im allgemeinen sollte man aber Steuerelemente nicht serialisieren.
    Verlagere die Informationen in eine eigenständige Klasse, in der Du die zu persistierenden Werte unterbringst.

    Eine mögliche Variante hatte ich gezeigt in: UserControl Werte an Form übergeben....
    Dort waren es mehrere Formulare, aber vom Prinzip kann man das dortige Konzept für jeden Zweck verwenden
    und die Datenbindung ebenso einsetzen.

    Reicht Dir eine binäre Serialisierung müsstest Du die Klasse nur als Serializable kennzeichnen.
    Alternativ kannst Du aber auch die Xml Serialisierung verwenden.

    Eine weitere Möglichkeit wäre die Werte als Anwendungseinstellungen (je Benutzer) zu speichern.

    Gruß Elmar

    • Als Antwort markiert eutrom Donnerstag, 15. Dezember 2011 13:41
    Donnerstag, 15. Dezember 2011 10:52
  • Danke für die Antwort, das mit den Anwendungseinstellungen klingt schon interessant. Trotzdem bin ich der Meinung es muss auch mit weniger Aufwand zu erreichen sein, beim nächsten Mal denke ich aber dran.

    wie oben steht wird fileName im FileOK-Event gesetzt. Wers genau wissen will:

            void file_FileOk(object sender, System.ComponentModel.CancelEventArgs e)
            {
                fileName = Convert.ToString(((OpenFileDialog)sender).FileName); //Convert um ganz sicher zu gehen
                //fileName = ((OpenFileDialog)sender).FileName; klappt auch nicht

     

    Es ist übrigens ne WPF-Anwendung.

    Wer jetzt noch wissen will wieviel Arbeitsspeicher und welche Grafikkarte mein Rechner hat soll bitte einfach kein Kommentar schreiben.

     


    • Bearbeitet eutrom Donnerstag, 15. Dezember 2011 11:49
    Donnerstag, 15. Dezember 2011 11:28
  • Hallo,

    naja, wenn Du das bereits so genau weißt, wieso hast Du dann Probleme?
    (Und Dein Rechner interessiert mich (und C#) herzlich wenig).

    Wenn das Ereignis ausgeführt wird (verknüpft wurde), so sollte fileName einen Wert enthalten,
    auch ohne Sicherheitsmassnahmen. Wohin er sich später verflüchtig, ist immer noch nicht ersichtlich.

    Einfacher und zuverlässiger wäre, die Variable beim Ausführen des Dialogs zu füttern:

      if (openFileDialog1.ShowDialog() == DialogResult.OK)
      {
          this.fileName = openFileDialog.FileName;
      }
      else
      {
          this.fileName = String.Empty;
      }
    
    
    

    Gruß Elmar

    Donnerstag, 15. Dezember 2011 11:58
  • Das ist C#??? ;)

    Spaß beiseite, habs nicht böse gemeint aber wenn ich manche Foren so lese stehen da lauter unnütze Antworten wie "Du musst schon genauer schreiben was du machen willst" oder "Wir können ja gar nicht wissen was du für ein System hast" obwohl es gar nichts mit dem Problem an sich zu tun hat, und am Ende ist überhaupt keine richtige Antwort da.

    Hab das tatsächliche Problem lokalisiert:

    Da ich will dass die Serialisierungsdatei im gleichen Verzeichnis landet in dem auch die fertige Anwendung liegt habe ich keinen Pfad angegeben sondern nur den Dateinamen:

    FileStream stream = new FileStream("config.txt", FileMode.Create);

    In diesem Fall scheint die FileStream-Klasse den Pfad durch Environment.CurrentDirectory zu ermitteln. Nachdem aber das OpenFileDialog offen war ändert sich die Eigenschaft CurrentDirectory, die Datei wird also dorthin geschrieben wo sich die zuletzt geöffnete Datei befindet. Geladen wird es aber beim Start natürlich wieder aus dem Verzeichnis wo die Anwendung ist.

    Habe es also nun in  FileStream stream = new FileStream(AppDomain.CurrentDomain.BaseDirectory +"config.txt", FileMode.Create); gändert und es funktioniert.

     


    • Bearbeitet eutrom Donnerstag, 15. Dezember 2011 13:28
    • Als Antwort markiert eutrom Donnerstag, 15. Dezember 2011 13:41
    Donnerstag, 15. Dezember 2011 13:23
  • Hallo,

    an der Aussage von Nr 5: "Ich brauche mehr Input" könnte manchmal (nicht immer) was dran sein ;-)

    Das Ablegen von Informationen im Anwendungsverzeichnis sollte man unterlassen,
    (wie das mit den Steuerelementen eigentlich auch - aber Schwamm drüber )
    Denn dort hat ein Normalbenutzer unter Vista / Windows 7 keinen schreibenden Zugriff.

    Die packt man in die dafür vorgesehenes Verzeichnisse siehe
    http://stackoverflow.com/questions/147016/where-to-put-common-writable-application-files
    Zu ermitteln in .NET Environment.GetFolderPath
    und je nach Absicht mit LocalApplicationData, ApplicationData oder CommonApplicationData

    Zum Verzeichniswechsel durch den Dateidialog: Dort gibt es die Eigenschaft RestoreDirectory.
    Wobei der vorsichtige Entwickler sich nie auf das aktuelle Verzeichnis verlässt,
    sondern vollständige Pfade vorzugsweise via Path.Combine bildet.

    Gruß Elmar

    Donnerstag, 15. Dezember 2011 13:45