stell die Frage besser andersrum: Wann braucht man keinen Anweisungsblock?
Du brauchst ihn nämlich immer, ausser der Block besteht nur aus einer einzigen Anweisung.
Nur in diesem Spezialfall kann man sich den Anweisungsblock mit den geschweiften Klammern sparen.
Weiß jemand wieso es nicht mehr funktioniert wenn es einmal ausgeführt wurde???
Nein. Aber eine Vermutung hätte ich anzubieten:
Wie sieht denn die Stelle aus, an der Du die Funktion an das click-Ereignis des Buttons hängt?
Möglicherweise hast Du da einen Funktionsaufruf stehen, statt die Funktion als Handler zuzuweisen.
Allerdings hast Du ja schon ein serverseitiges Control, in dem Du das versuchst. Das sollte den Pfad eigentlich automatisch auflösen, wenn Du es so wie im Startbeitrag machst. Könnte allerdings sein, dass das Auflösen erst passiert, wenn ein DataBind-Aufruf erfolgt. Hast Du so einen irgendwo in Deiner Page?
Wenn das alles nichts hilft, poste doch bitte mal den fertig gerenderten HTML-Code (Quelltextansicht im Browser), damit man genau sieht, was er aus Deinem Pfad bastelt.
ich würde definitiv Variante 1 bevorzugen, ich finde das besser lesbar.
Was der Compiler draus baut, ab ich mir nicht angeschaut - kann gut sein dass er genau das Gleiche aus beiden Varianten baut. Auch beim Jitter könnte das noch passieren.
Einen numerischen Wert zu einem Leerstring zu "addieren" fühlt sich für mich einfach falsch an.
Mal davon abgesehen, dass in der zweiten Variante ohnehin auch ToString auf dem Counter aufgerufen wird.
Gruß, MarsStein
Edit:
In neueren C#-Versionen kannst Du aich String interpolation nutzen, das ist auch eine schöne und gut lesbare Variante:
\n\r sieht man immer wieder, ist aber falsch (in der Praxis macht es aber meist nichts aus).
Das sollte - wenn zusammen benutzt - immer \r\n sein (carriage return - line feed, nicht line feed - carriage return).
Ich würde an Deiner Stelle Environment.NewLine nutzen, das sollte plattformabhängig immer den richtigen Wert liefern (bei mir \r\n )
unabhängig davon, ob die die Antwort benötigst oder nicht, musst Du auf jeden Fall noch auf dem WebRequest die GetResponse-Methode aufrufen. Erst dadurch wird der Request an den Server abgesetzt. Habe ich aber in dem verlinkten Thread im letzten Post auch geschrieben.
Meine ucls kriegen über d:DataContext bereits im Designmode mitgeteilt, welches Viewmodel sie darstellen sollen. Sie sind nicht als allgemein-verwendbar gedacht, wie etwa eine Textbox oder ein DatetimePicker.
Völlig OK meiner Ansicht nach. Wie gesagt, ist das für mich eine Frage des Anwendungsfalls.
Das jedenfalls ganz und gar nicht.
Wenn Du im UserControl einzelne Controls hast, die mit Werten aus einem VM gebunden werden sollen, dann gibt es 2 Möglichkeiten:
Entweder das UserControl trifft bereits Annahmen über das ViewModel (weiß also schon, wie dort die Properties benannt sind, damit man binden kann). Dann gibst Du dem UC einen DataContext, der die entsprechenden Properties enthält, und das Ganze funktioniert so wie Du es beschreibst. Dann bist Du aber auch gezwungen, ein solches ViewModel zu implementieren, dass zum UC passt.
Oder Du gehst noch einen Schritt weiter und entkoppelst das vollständig.
Dann halt auf die Art wie von MrSparkle beschrieben. Dann muss das UserControl überhaupt nix mehr über die Struktur des ViewModels wissen, aus dem die Daten kommen. Es können sogar die im UC angezeigten Werte aus unterschiedlichen ViewModels kommen. Dann kannst Du so ein UC wiederverwendbar machen, ohne bereits die ViewModel-Klasse dazu vorzugeben -> so ist es ja auch im Framework selbst, die ganzen Controls dort sind einfach nur Controls, aber ViewModels gibt es da noch nicht. Die schreibt der Benutzer des Controls eben selbst.
Edit: ich selbst benutze beide Varianten (bin da nicht puristisch), je nach Anwendungsfall des UC.
Eine DependencyProperty brauchst du hier nicht. Die würdest du nur brauchen, wenn du darauf per Binding zugreifen möchtest.
Das ist zwar richtig.
Die deutlich bessere Herangehensweise wäre aber in 99% der Fälle, die Werte in einem ViewModel zu speichern und dann an das UserControl zu binden.
der Stacktrace wird beim Debuggen angeigt (falls bei Dir nicht, kannst Du das Fenster über das Debug-Menü einblenden DEBUG->Windows->Call Stack).
Zusätzlich steckt der Stacktrace aber auch in der Exception selbst als Property StackTrace.
Edit: In der Exception steckt der relevante Callstack beim Auslösen der Exception (auch wenn sich da nicht immer was sinnvolles findet).
Das muss nicht derselbe sein, wie in dem Debug-Fenster. In letzterem kannst Du während des Debuggens immer den aktuellen Callstack sehen.
ich habe mir jetzt mal angesehen, was da eigentlich im Hintergrund passiert:
WPF benutzt den PropertyChangedEventManager, einen spezialisierten WeakEventManager, um auf die PropertyChanged Events des VM zu reagieren.
Ich beziehe mich im Folgenden auf die Codezeilen aus der verlinkten Quelle.
Irgendwann wird die AddListener-Methode (276) aufgerufen, diese ordnet dem Quellobjekt (dem VM oder genauer: dem Source-Objekt des Bindings) ein Dictionary zu (287), in dem zum gewünschten Propertynamen - der ja über das Binding bekannt ist - eine Liste mit den benötigten Handlern gehalten wird.
Anschließend wird in (290) die Methode StartListening (150) aufgerufen, welche das PropertyChanged-Event abonniert.
Der registrierte Handler findet sich ab (378). Dort wird zunächst versucht, das dem Quellobjekt (diesmal sender) zugeordnete Dictionary zu finden (387). Wird es nicht gefunden, wird eine leere Handlerliste benutzt (389-394), und damit bist Du aus der Nummer raus.
Genau das ist hier der Fall: Da der sender der Typ und nicht das Quellobjekt ist, existiert auch kein Dictionary dazu, und es passiert nichts mehr weiter.
WPF bzw. der PropertyChangedEventManager geht also sehr wohl davon aus, dass das Objekt als sender übergeben wird, das die geänderte Property enthält. An einem kleinen einfachen Beispiel konnte ich das auch genau so nachvollziehen.
Zitat
da sont auch alle PropertyChangedEvents nicht abgehohlt würden. Dies ist jedoch der in allen Datenrelevanten Properties der fall, also muss meines erachtens dies keine Rolle spielen.
Der oben gezeigte Mechanismus - sofern ich ihn richtig verstanden habe - verleitet mich dazu, das Gegenteil zu behaupten.
Das kann eigentlich nur funktionieren, wenn da ganze DataContext-Objekte ausgetauscht werden, oder ObservableCollections geändert werden, dann läuft das ganze wieder etwas anders. Die Gegenrichtung - Updaten des ViewModels aus der View - ist natürlich auch nicht betroffen.
Ich glaube, dass Du da einem Trugschluss aufgesessen bist. Die Bindings funktioneren zwar initial, Änderungsbenachrichtigungen direkt vom ViewModel über INPC kann die View aber auf diese Weise nicht erhalten.
Also tu Dir selbst den Gefallen und probier es einfach einmal aus, statt Dich auf Dein seltsames Konzept zu vesteifen - das funktioniert nämlich schlichtweg nicht.
möglicherweise funktionieren Deine Properties auch mit dem Typen. Da würde ich mich aber jedenfalls nicht drauf verlassen - Gründe stehen oben.
Das Event wird ja von Framework-Klassen konsumiert, und nicht von Dir selbst. Da könnte es dann fallweise implementierungsabhängig sein, ob und wie die Events konsumiert werden.
Früher stand das als Konvention explizit in der Doku: Raising an Event
Zitat von MSDN
By convention, events in the .NET Framework have the signature EventName(sender, e), where sender is an Object that provides a reference to the class or structure that fired the event
Der Artikel wurde allerdings überarbeitert, und diese Konvention ist nicht mehr explizit genannt.
Andere Sache, von der ich aber nicht glaube, dass sie Dein Problem auslöst: Mode=OneWay und UpdateSourceTrigger passen nicht wirklich zusammen.
also mit dem Typen kann es nicht funktionieren. Du brauchst auf jeden Fall das konkrete Objekt als sender.
Stell Dir einfach mal vor, Du hast mehrere Deiner VM-Objekte in verschiedenen Views, eines davon ändert sich, das andere nicht. Wie soll denn über den Typen entschieden werden, welche View dann aktualisiert werden soll?
Es wird nicht automatisch nach Uhrzeit berechnet, sondern rein nach "Zahlen"
Eigentlich werden hier lediglich Zeitspannen miteinander verglichen. In der Uhrzeit steckt ja keine Information über den Tag bzw. Tageswechsel.
6:00 kann eben genausogut am gleichen Tag wie die 17:00 liegen, oder eben am nächsten Tag.
Die Reihenfolge in der Du die Werte vergleichst kann und darf hier keine Rolle spielen.
Ob also ein Tageswechsel vorliegt, musst Du daher in irgendeiner Weise selbst entscheiden.
Möglich wäre z.B. auch, sich ein fixes Datum zu nehmen und dann mit dem vollständigen DateTime (nicht TimeSpan) Differenzen zu dem fixen Datum zu bilden (die dann doch wieder ein TimeSpan sind, der aber dann die Information über den Tageswechsel schon enthält), das halte ich aber für ungleich komplizierter.
bei genauerem Hinsehen frage ich mich, wie da überhaupt irgendwas funktioniert:
Du erstellst beim ersten Aufruf ein State-Objekt und steckst einen in der Methode lokal erzeugten Puffer rein. Allerdings greifst Du nach dem Lesen gar nicht auf diesen Puffer zu...
Irgendwo innerhalb der RecieveCallback müsste doch auch mal s.Data zugegriffen werden.
Ich frage mich, wie Dein readMessage überhaupt an die Daten kommt.
kann man IMO schon so machen -> In der Callback wird direkt der nächste asynchrone Lesevorgang gestartet, das sollte funktionieren.
Aber die Aufrufreihenfolge ist seltsam, ich würde auf jeden Fall zunächst mal über EndReceive die vorhandenen Daten lesen, und erst danach wieder BeginReceive aufrufen.
da kann ich mir jetzt irgendwie nicht so richtig vorstellen, was Du willst.
Kannst Du mal ein Bild anhängen, wie Du Dir grob eine solche "grafische Übersetzung" vorstellst?
Im konkreten Fall handelt es sich bei sender um ein object, das hier auf ein Control gecastet wird, um auf die Eigenschaften/Methden des Controls zugreifen zu können.