Jeff.Jefferson Geschrieben 18. Mai 2011 Geschrieben 18. Mai 2011 Hi Community, eine sehr faszinierende Sache an WPF ist meiner Meinung nach, die Möglichkeit ganze Objekte während der Laufzeit in XAML-Format abzuspeichern bzw auch wieder einzulesen. Ich habe ein TreeView. Bei einer Änderung des besagten TreeView's wird das TreeView Objekt in XAML abgespeichert. Bei einem Programmstart soll - sofern vorhanden - das TreeView-XAML-File eingelesen werden. Es ist wirklich ganz simpel using (System.IO.FileStream fs = new System.IO.FileStream(System.IO.Directory.GetCurrentDirectory() + "\\TreeView.xaml", System.IO.FileMode.Open)) { TreeView treeMain = (TreeView)System.Windows.Markup.XamlReader.Load(fs); } so wird ein beim Programmstart anhand der XAML Datei ( die per XamlWriter.Save(object) erstellt und durch einen Streamwriter abgespeichert wurde) ein TreeView Control erstellt. Sehr angenehme Funktion Nun will ich aber kein neues Treeview Control Erstellen, ich will ein vorhandenes ersetzen. (Für die Leute die jetzt fragen "warum?" - weil es ja eigentlich egal ist ob ich ein vorhandenes TreeView beim Programmstart überschreibe oder ob ich ein neues erstelle, da man das überschriebene ja niemals un-überschrieben sehen wird: Nunja, es geht mir einfach darum, dass ich in VS2010 in der xaml/Entwurf-Ansicht mein layout entwerfe und das nicht geht wenn ich erst in der CodeBehind-Datei mein TreeView erstelle und dann meiner Oberfläche hinzufüge. Nun aber zurück zu meinem Problem. Erstaunlich finde ich nämlich, dass beim Einzelschritt-Debugging mein TreeView (welches ich überschreiben will) tatsächlich überschrieben wird. Es wird mir aber nicht visuell angezeigt. Hier ein Paar Screens, die mein Problem verdeutlichen: Debugging bevor eingelesen wurde Debugging nachdem eingelesen wurde Ansicht nach dem Debuggen wie man sieht, werden keine Elemente angezeigt, obwohl es welche gibt Achja: Es liegt nicht am treeView selbst, ich habe das ganze auch schon mit IMAGE-Controls versucht. Neu anfügen: kein problem. überschreiben: No Way ! Es gäbe natürlich die Option beim Programmstart ein neues TreeView zu erstellen und dessen einzelne Items an mein MainTreeView zu übergeben. Meiner Meinung aber eher eine unsaubere Lösung. Es muss doch eine einfache "Neuzeichnen-Methode" oder so geben. Finde ich aber nicht ! Kann mir jemand helfen ? Zitieren
NerdonRails Geschrieben 18. Mai 2011 Geschrieben 18. Mai 2011 public static class ExtensionMethods { public static void Refresh(this UIElement uiElement) { uiElement.Dispatcher.Invoke(new Action(() => {}), DispatcherPriority.Render); } } Evtl. mit dem Code oben das element neu rendern. Zitieren
Jeff.Jefferson Geschrieben 20. Mai 2011 Autor Geschrieben 20. Mai 2011 public static class ExtensionMethods { public static void Refresh(this UIElement uiElement) { uiElement.Dispatcher.Invoke(new Action(() => {}), DispatcherPriority.Render); } } Evtl. mit dem Code oben das element neu rendern. Hab den Code wie folgt Implementiert, da ich nicht genau deine Parameterübergabe vestanden hab using (System.IO.FileStream fs = new System.IO.FileStream(System.IO.Directory.GetCurrentDirectory() + "\\TreeView.xaml", System.IO.FileMode.Open)) { treeMain = (TreeView)System.Windows.Markup.XamlReader.Load(fs); treeMain.Dispatcher.Invoke(new Action(() => { }), System.Windows.Threading.DispatcherPriority.Render); } bringt aber nix danke trotzdem Zitieren
SeToY Geschrieben 20. Mai 2011 Geschrieben 20. Mai 2011 Das, was NerdonRails geschrieben hat, war eine ExtensionMethod. Wenn du nun ein Objekt vom Typ "UIElement" hast, (wahrsch. dein TreeView) kannst du mittels "object.Refresh();" diese Methode ausführen. using (System.IO.FileStream fs = new System.IO.FileStream(System.IO.Directory.GetCurrentDirectory() + "\\TreeView.xaml", System.IO.FileMode.Open)) { treeMain = (TreeView)System.Windows.Markup.XamlReader.Load(fs); treeMain.Refresh(); } Zitieren
Jeff.Jefferson Geschrieben 20. Mai 2011 Autor Geschrieben 20. Mai 2011 achso, ich bin gerade dabei WPF zu lernen, war noch nicht bei ExtensionMethods. Die Syntax "this UIElement uiElement" hatte mich verwirrt^^ Zitieren
SeToY Geschrieben 20. Mai 2011 Geschrieben 20. Mai 2011 ExtensionMethods gibts ja auch nicht erst seit WPF ;p Diese Syntax übergibt der Methode das Element "uiElement" des Typen "UIElement" und führt mit diesem dann die Methode aus... Rein theoretisch hätte deine Version dann so funktionieren müssen: uiElement.Dispatcher.Invoke(new Action(() => {}), DispatcherPriority.Render); --> [U]treeMain[/U].Dispatcher.Invoke(new Action(() => {}), DispatcherPriority.Render); Zitieren
Jeff.Jefferson Geschrieben 20. Mai 2011 Autor Geschrieben 20. Mai 2011 ExtensionMethods gibts ja auch nicht erst seit WPF ;p Das hatte ich schon befürchtet kurz nachdem ich den Post verfasst hab^^ Aber [...] übergibt der Methode das Element "uiElement" des Typen "UIElement" und führt mit diesem dann die Methode aus Ist das nicht das selbe Verfahren wie bei jeder anderen "normalen" Methode, die ein object (per Referenz) als Parameter entgegennimmt ? z.B public static void Normal_Refresh(ref UIElement uiElement) { uiElement.Dispatcher.Invoke(new Action(() => {}), DispatcherPriority.Render); } das "this" vor dem Parameter war mir neu^^ aber ich les mir einfach mal den msdn artikel dazu durch... Zitieren
NerdonRails Geschrieben 20. Mai 2011 Geschrieben 20. Mai 2011 Ist das nicht das selbe Verfahren wie bei jeder anderen "normalen" Methode, die ein object (per Referenz) als Parameter entgegennimmt ? z.B public static void Normal_Refresh(ref UIElement uiElement) { uiElement.Dispatcher.Invoke(new Action(() => {}), DispatcherPriority.Render); } Nein, Extension-Methods kann man im Gegensatz zu normalen Methoden wie von dir Aufgeführt auf ein Objekt aufrufen. Also sowas wie myTreeView.Refresh() anstatt MyStaticClass.NormalRefresh(myTreeView). Syntaktischer Zucker der zu besserer Lesbarkeit beiträgt. Weiterhin bieten Extension-Methods die möglichkeit, Klassen, die sealed sind um Methoden zu erweitern. So könnte man z.B. Int32 um eine IsEven()-Method erweitern. public static class Extensions { public static Boolean IsEven(this Int32 value) { return value % 2 == 0; } } 2.IsEven() // => true Weiterhin wäre das ref bei deiner Methode nicht nötig, da alles bis auf Datentypen die von Struct ableiten (Int32, Double, enums etc.) Referenzdatentypen sind. Zitieren
Jeff.Jefferson Geschrieben 24. Mai 2011 Autor Geschrieben 24. Mai 2011 Syntaktischer Zucker der zu besserer Lesbarkeit beiträgt. Gut, darauf wollte ich hinaus. Also mir ist nicht der Sinn klargeworden. Das Ergebnis unterscheidet sich ja nicht von einer normalen Methode, die das Objekt als Parameter übergeben bekommt. Aber wie du ja sagst Weiterhin bieten Extension-Methods die möglichkeit, Klassen, die sealed sind um Methoden zu erweitern. gibt es doch einen Vorteil für Extension-Methods... Aber mal zurück zu meinem ursprünglichen Problem.... Momentan hab ich ne "schmutzige" Alternative implementiert... Hab in meinem Programm ein TreeView als Child eines StackPanels (damit arbeite ich dann im Entwurfs-Modus...) und naja, anstatt das jetzt zu überrschreiben, lösch ich einfach das besagte Child Element und füge am alten Index das neu-erzeugte TreeView ein..... Aber ich versteh es einfach nicht.... es muss doch auch ne Möglichkeit geben das überschriebene Objekt sichtbar zu machen Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.