Laden...

Problem mit Clipboard.SetData()

Erstellt von punkdevil vor 16 Jahren Letzter Beitrag vor 16 Jahren 4.817 Views
P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 16 Jahren
Problem mit Clipboard.SetData()

Hallo,

ich möchte ein Objekt vom Typ AbstractTreeNode (abgeleitet von TreeNode) in die Zwischenablage kopieren, um es anschließend woanders einzufügen.

Das kopieren in die Zwischenablage mache ich mit folgenden zwei Zeilen Code:


DataObject obj = ((AbstractTreeNode)tv.SelectedNode).GetDataObject();
Clipboard.SetData("AbstractTreeNode", obj);

Wenn ich mir nun später, den AbstractTreeNode wieder aus der Zwischenablage holen möchte bekomme ich null zurück.


Clipboard.GetDataObject().GetData("AbstractTreeNode")

Allerdings die Abfrage, ob Daten in dem angegebenen Format vorliegen ist true:


Clipboard.GetDataObject().GetDataPresent("AbstractTreeNode")

Hat jemand ne Ahnung woran das liegt, bzw. was ich falsch mache?

915 Beiträge seit 2006
vor 16 Jahren

Hallo punkdevil,
bei Clipboard.SetData solltest du die DataFormats beachten.

Du hast zwar einen Wert in die Zwischenablage gespeichert aber das ist der Text von AbstractTreeNode.ToString().
Um die Klasse in die Zwischenablage zu kopieren musst sie Serialisierbar machen. Hier der Link zur MSDN Seite.

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 16 Jahren

Hallo Andreas,

also, die klasse ist serialisierbar.

und mit


Clipboard.SetData("AbstractTreeNode", obj);

gebe ich ja das Format "AbstractTreeNode" an.

Clipboard.SetData() erwartet ja einen String zur Angabe des Formats und kein DataFormat-Objekt.

915 Beiträge seit 2006
vor 16 Jahren

Hrm, wenn wie im Link vorgegangen bei dem Beispiel für C#.
Sollte es zu keinen Problemen kommen.

Hast du das [Serializable] Attribut über deiner AbstractTreeNode wirklich gesetzt und bedenke AbstractTreeNode klingt komisch.
Würde vermuten das dass Ding ne Abstrakte Klassen ist und diese kann man nicht instanziieren und somit serialisieren. Ansonsten vergewissere dich das die Klasse auch einen Konstruktor ohne Parameter hat.

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 16 Jahren

Die Klasse AbstractTreeNode ist abstract. Davon habe ich mehrere Klassen abgeleitet.
Objekte dieser abgeleiteten Klassen sollen in die Zwischenablage kopiert werden.

Ich habe es jetzt exakt wie in dem Link angegeben gemacht:


DataFormats.Format myFormat = DataFormats.GetFormat("AbstractTreeNode");
DataObject obj = new DataObject(myFormat.Name, tv.SelectedNode);
Clipboard.SetDataObject(obj);
IDataObject get= Clipboard.GetDataObject();
AbstractTreeNode node = (AbstractTreeNode)get.GetData(myFormat.Name);

Das Ergebnis ist das gleiche. GetDataPresent(myFormat.Name) liefert true, aber GetData(myFormat.Name) liefert null.

915 Beiträge seit 2006
vor 16 Jahren

Hrhr, tu mir mal einen gefallen - geh in die Klasse AbstractTreeNode und schreib statt


public abstract class AbstractTreeNode 

mal folgendes hin:


public class AbstractTreeNode 

Probiers jetzt noch mal 😉

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 16 Jahren

Das hat leider nichts gebracht...

915 Beiträge seit 2006
vor 16 Jahren

Hrm, hatte es auch grade etwas verpeilt...

Da TreeNode ja nicht von deiner abstrakten Basisklasse abgeleitet ist und somit nicht gecastet werden kann geht das ganze auch so nicht. Bei deinen zweiten Beispiel genau das selbe in GetData. Wenn da statt AbstractTreeNode eben TreeNode nimmst sollte es funktionieren.

Allgemein ist es aber möglich eine normale Klasse, die von einer abstrakten Klasse abzuleiten und sofern beide serialisierbar sind auch in eine abstrakte Klasse zurück zu casten und diese zu serialisieren.
Aber darum ging es dir ja nicht, bzw. wüsste grade nicht wofür man ein so komisches gebilde bräuchte 🙂

Ich habs einfach nur wie folgt getestet, hab ne Klasse erstellt von TreeView abgeleitet und die OnMouseDown Methode überschrieben, mir das gefundene object in die Zwischenablage gelegt und bei nen Button-Click wieder ausgegeben. Hatte ohne Probleme funktioniert. Bzw. das ganze kann man ja auch beliebig anders lösen, der Weg ist immer nur der selbe - Die meisten Control spezifischen objekte sind wegen der DragAndDrop Geschichte ja eh schon serialisierbar, also muss man da in den seltesten Fällen etwas machen. Also, Datenholen, in dem Fall den Knoten diesen ins Clipboard schmeissen und wieder rausholen.

Zusammengefasst sieht das so aus, was ebenso geht.


        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (e.Button == MouseButtons.Left)
            {
                TreeNode node = base.GetNodeAt(e.Location);

                if (node != null)
                {

                    // copie node into the clipboard.
                    Clipboard.SetData(DataFormats.Serializable, node);

                    // get node from clipboard.
                    TreeNode mynode = (TreeNode)Clipboard.GetData(DataFormats.Serializable);
                }
            }
        }

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 16 Jahren

OK, mit DataFormats.Serializable habe ich es noch nicht probiert. Da habe ich, wie es zum Beispiel im Openbook von Galileocomputing steht, einen String zur Bezeichnung des Formats übergeben.

Ich werde auch mal probieren statt AbstractTreeNode, einfach treeNode zu nehmen.

Ich kann es aber morgen früh erst ausprobieren.

Was halt irgendwie komisch ist, das GetDataPresent true zurück liefert. D.h. ja, das in der Zwischenablage die Daten in dem entsprechenden Format zur Verfügung stehen...

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 16 Jahren

Guten morgen,

ich bin leider noch nicht weiter gekommen.

Also mit "normalen" TreeNodes gehts.


Clipboard.SetData(DataFormats.Serializable, new TreeNode("Test");
if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Serializable))
{
    Object objGet = Clipboard.GetData(DataFormats.Serializable);
    TreeNode node = (TreeNode)objGet;
}

Das Ergebnis ist ein gültiger TreeNode.

Wenn ich dagegen einen Knoten, abgeleitet von TreeNode verwenden:


Clipboard.SetData(DataFormats.Serializable, tv.SelectedNode);
if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Serializable))
{
      Object objGet = Clipboard.GetData(DataFormats.Serializable);
      AbstractTreeNode node = (AbstractTreeNode)objGet;
}

Hier bekomme ich in der letzten zeile eine InvalidCastException: System.IO.MemoryStream kan nicht in AbstractTreeNode gecastet werden.

5.299 Beiträge seit 2008
vor 16 Jahren

Hi!

Was willst du machen?
Ich denke, innerhalb derselben Anwendung ist man nicht unbedingt aufs Clipboard angewiesen, sondern nur beim Austausch mit anderen Anwendungen. Und einer anderen Anwendung muß man den Typ "AbstractTreenode" erstmal bekannt machen, das geht nur per strong named Dll (glaubich).

Der frühe Apfel fängt den Wurm.

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 16 Jahren

Hallo ErfinderDesRades,

klar kann ich es auch anders machen, aber ich dachte über die Zwischenablage ist vielleicht eine elegante Variante.

915 Beiträge seit 2006
vor 16 Jahren

Also, TreeNode ist implementiert ja deine deine Klasse AbstractTreeNode Klasse nicht.

Aber ich denke eher du hast eine Klasse die von AbstractTreeNode ableitet und AbstractTreeNode leite von TreeNode ab. Wenn jetzt new TreeNode("Test") übrergibst kann es ja nur zu Fehlern kommen 🙂 Wenn deine Klasse die von AbstractTreeNode abgeleitet wurde mit Nodes.Add(new KlasseDieVonAbstractTreeNodeAbgeleitetIst) hinzufügst. Wird es dennoch nicht klappen.

Da TreeNode von MarshalByRefObject abgeleitet ist und die Schnittstellen ICloneable, ISerializable beinhaltet kommt es ebenso zu fehlern.

Also, du hast gar keine andere wahl als die Klasse TreeNode zu verwenden. Ansonsten müsstest du eine Hilfsklasse nutzen in der die Daten von TreeNode übergibst. Sowas könntest entweder über Reflection lösen oder machst es via parameter übergabe.

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

P
punkdevil Themenstarter:in
992 Beiträge seit 2007
vor 16 Jahren

Hallo Andreas,

also SelectedNode habe ich in meinem TreeView überschrieben und es liefert einen AbstractTreeNode zurück.

Aber egal, ich habe es jetzt ohne Zwischenablage gelöst, in dem ich mir halt einfach den AbstractTreeNode merke, der kopiert wurde.

Trotzdem vielen Dank!