Laden...
L
Lynix myCSharp.de - Member
Software-Entwickler Saarland Dabei seit 08.04.2004 667 Beiträge
Benutzerbeschreibung

Forenbeiträge von Lynix Ingesamt 667 Beiträge

13.01.2012 - 09:16 Uhr

Hallo zusammen,

für mich gehört in einem perfekten Sourcecode jede Code-Zeile, die nicht trivial ist, d.h. in der nicht bloß eine Variableninitialisierung oder eine Wertzuweisung o.Ä. stattfindet, dokumentiert. In diesem Sinne kann man eigentlich garnicht genug Kommentare schreiben, und das Argument, zu viele Kommentare würden einen Sourcecode unübersichtlich machen, sehe ich nicht ein. Das mag vielleicht so sein, wenn man mit notepad.exe programmiert, aber wer tut das heutzutage noch ?

12.01.2012 - 18:52 Uhr

Hallo herbivore,

ich kann Deinen Punkten nicht oder nur begrenzt zustimmen.

•Es fängt damit an, dass es (Arbeits-)Zeit kostet, Kommentare zu erstellen.

Einen unkommentierten Fremdcode nachvollziehen zu müssen ist ab einer gewissen Mindestkomplexität sicherlich Zeit- und damit auch Kostenintensiver.

•Dann müssen Kommentare an Codeänderungen angepasst werden, die müssen also aktuell gehalten werden.

Das stimmt natürlich, ist aber kein "Nachteil eines Kommentars". Die Alternative, keine Kommentare zu nutzen ist sicherlich nicht besser als der unbestrittene Fakt, dass Kommentare auch gepflegt werden müssen.

•Das kann vergessen werden und zu Inkonsistenzen führen.

Stimmt, aber von vorneherein keine Kommentare zu machen kann dagegen dazu führen, dass ein Entwickler tage- oder wochenlang versucht einen Code nachzuvollziehen, der mit einem Kommentar sofort klar wäre.

•Wenn die Änderungen nicht vergessen werden, kosten sie erneut Zeit.
•Je mehr und je längere Kommentare existieren, desto mehr Zeit kosten die Aktualisierungen und desto eher übersieht der Änderer notwendige Aktualisierungen.

siehe Punkt 1 - dass es Zeit kostet und gepflegt werden muss ist klar, aber mit dieser Argumentation könnte man auch sagen "Programmieren ist ein Nachteil" oder "Zähne putzen ist ein Nachteil".

•Selbst wenn Kommentare keine überflüssigen Informationen enthalten, können sie den Code auseinander ziehen/reißen und dadurch die Übersichtlichkeit verringern.

Ich bleibe dabei, dass ordentlich formatierte Kommentare einen Code nicht unübersichtlicher machen. Das passiert nur wenn man es gezielt darauf anlegt wie
Winsharp93 es oben in einem Extrembeispiel gezeigt hat.

•Selbst mit guter Absicht und Sorgfalt erstellte Kommentare können inhaltlich falsch oder missverständlich formuliert sein und dadurch schaden.

Diesen Punkt lasse ich bedingt gelten, wobei es auch hier nicht um einen Nachteil des Kommentierens geht, sondern um die Kommunikationsfähigkeit des Mitarbeiters. Dieses Problem besteht bei allen Arbeitsabläufen, bei denen zwei oder mehr Personen miteinander kommunizieren müssen.

•Selbst in mit guter Absicht und Sorgfalt erstellten Kommentare können gerade die Informationen fehlen, die ein späterer Leser mit einem anderen Erfahrungshintergrund benötigt.

Worin liegt dann der Nachteil im Vergleich dazu gleich garkeinen Kommentar zu hinterlegen ?

12.01.2012 - 10:25 Uhr

Also throw new Exception ist Murks, wie ja bereits ausreichend in diesem Thread gesagt wurde. Wenn Du unbedingt ein AutoresetEvent nutzen willst, dann nimm die WaitOne() Überladung, die einen Timeout-Parameter akzeptiert um die Blockade nach einer geeigneten Zeit X abzubrechen. Das in Verbindung mit dem Vorschlag von xxMUROxx sollte schonmal dazu führen, dass Du die Schleife gezielt sauber beenden kannst.

12.01.2012 - 10:17 Uhr

Ist ja klar, dass Du nur Bahnhof verstehst, der Klassenname sagt ja auch nicht aus, wie man damit arbeiten musst. Hast Du denn mal nach den genannten Stichworten gesucht ? Oder willst Du jetzt eine fertige Lösung haben ?

11.01.2012 - 22:43 Uhr

Naja, Du kannst Deine Methode ja auch mit Brainfuck.NET programmieren, dann kann den ach so simplen Code auch niemand mehr entziffern. Will sagen, Dein Beispiel ist albern... wenn jemand anfängt zu kommentieren, was ein Semikolon bedeutet, gehört er eher ans Fließband als vor einen PC. Und bei einem Kommentar für jedes Wort eine eigene Zeile zu benutzen oder alle Kommentare in den Code rein zu packen ohne Zeilenumbruch hat eher mit Sabotage als mit konstruktiver Arbeit zu tun.

Genausogut könntest Du den Code selbst, der ohne Kommentare auskommt, so beschissen formatieren und mit sinnlosen Operationen auffüllen, dass Du Deine Argumentation umkehren kannst.

11.01.2012 - 22:27 Uhr

Vielleicht liegt es dran dass der BOOL in C eine andere Größe hat als in C#? [...] Versuch mal einen int zurückzugeben [...]

Wenn es C ist nutzt ein Int nichts, dann müsste man stattdessen schon MarshalAs(UnmanagedType.I2) verwenden.

11.01.2012 - 22:22 Uhr

Was ist daran Gefrickel ? Das ist ein 3-Zeiler bei der der Aufruf einer Methode der Form-Klasse demonstriert wird. M$ frickelt ja oft und gerne, aber das hier finde ich noch ganz simpel realisiert.

11.01.2012 - 22:19 Uhr

Wenn Du schon Access benutzt, lad Dir Deine Datensätze in ein Dataset und Weise das Dataset einem Datagrid Control zu. Schon bekommst Du die Datensätze angezeigt.

Zum Zugriff auf eine Access-Datenbank solltest Du mal nach ADO.NET googeln, da gibt es massig Tutorials. Im Übrigen wird der DB-Zugriff über ADO standardisiert, so dass Du je nachdem ob Du Access, SQL oder was auch immer verwendest, meist nur noch den ConnectionString entsprechend anpassen musst.

11.01.2012 - 22:06 Uhr

Es gibt meiner Meinung nach keinen einzigen Grund, der dafür spricht, Kommentare einzusparen. Je mehr Kommentare, desto besser. Selbst wenn es nur Stating-The-Obvious ist, für den einen mögen Sachverhalte offensichtlich sein, für einen anderen, der einen Fremdcode vorgesetzt bekommt, vielleicht nicht. Hingegen sehe ich keine Nachteile in mehr Kommentaren, im schlechtesten Fall bringt ein Kommentar keinen Mehrgewinn, dann schadet er aber auch nicht.

Leider suchen viele immer nach Argumenten, warum Kommentare schlecht sind oder warum Kommentierung überflüssig ist, das liegt dann aber in 100% der Fälle an der Faulheit der Leute, die aber dann gern am Firmenstammtisch über den Code von jemand anderem herziehen "Voll scheiße, alles endlos verzweigt, nix kommentiert... wie soll man da denn durchblicken..."

11.01.2012 - 19:21 Uhr

Mal doch einfach das ganze Form in ein Bitmap und druck dieses aus.
Hier ein Beispiel, welches ich gerade auf die Schnelle bei google gefunden habe
Einen Screenshot mit C# machen

10.01.2012 - 16:57 Uhr

Hallo schismatic,

dein "Dauerspam" tritt dann auf, wenn ein BeginReceive sofort zurück kommt ohne etwas lesen zu können (bytesread > 0 == false). Dabei handelt es sich nicht um einen Spam des Clients sondern Deine Debug-Ausgabe "Read event occurred..." wird einfach schon ausgegeben bevor überhaupt erfolgreich gelesen wurde. Wenn der Socket tot ist, ist es allerdings schwierig erfolgreich zu lesen.

Kommen diese "Spam"-Ausgaben schnell hintereinander oder mit einiger Wartezeit dazwischen ? Es wäre interessant zu wissen, ob der Socket den Receive-Versuch einfach sofort abbricht und sofort zurück kommt oder ob er jedesmal in einen Timeout läuft.

10.01.2012 - 09:27 Uhr

Hallo herbivore,

vielleicht hast Du mich da missverstanden. Ein Property ist eine Eigenschaft, die einen Eigenschaftswert zurück liefert. Properties sollten aber nicht dazu missbraucht werden, zusätzlich zum Zurückliefern oder Setzen ihres Feldes noch weitere Zustände zu manipulieren. Schlimm wird es z.B. wenn ein Property Day neben dem Zurückliefern des (wie auch immer berechneten) Wertes noch die CultureInfo der Applikation oder das aktuelle Working Directory umsetzt.
Auch mit einer kleinen Multiplikation kann man Schindluder betreiben:


public int Value
{
  get { return mValue; }
  set { mValue = value * 5; }
}

myClass.Value = 7;
//...
//...
MessageBox.Show(myClass.Value); -> 35 -> häää?

Sowas ist einfach nicht intuitiv und kein Mensch kann das nach ein paar Wochen noch nachvollziehen.

Dass man alles missbrauchen kann ist klar, aber vielleicht ist es dem OP nicht klar, dass eine wie oben beschriebene Realisierung genau solch einen Missbrauch darstellt, deswegen denke ich der Hinweis sollte an dieser Stelle gestattet sein.

Ob es dabei um ein private oder public Property geht ist m.M. nach nebensächlich, denn selbst in dem Szenario, dass nur ein Entwickler an einem Projekt arbeitet (was bei dem OP ja nicht der Fall ist), weiß dieser Entwickler in 4 Wochen auch nicht mehr was sein Property intern tut.

Ein Beispiel welches aus dem Leben gegriffen ist, ist ein Property VoxelCoordinates, welches bei jeder Abfrage intern ein FixFPU aufrief. An anderer Stelle flogen dann sporadisch irgendwelche OverflowExceptions durch die Gegend und es dauerte mehrere Monate bis ich die Ursache des Fehlers durch Zufall gefunden hatte.

09.01.2012 - 19:25 Uhr

Hallo schismatic,

Ich würde dir auch erstmal empfehlen, den Socket-Thread jeweils geordnet zu beenden. Wahrscheinlich hast Du Deine Thread-Methode blockierend gebaut, weswegen Du den Thread nur noch über Abort() abschießen kannst. Hierfür gibt es bessere Lösungswege, die nicht blockieren. Wenn Du Deine Socket-Thread Methode mal postest, kann man Dir da sicher helfen.

Woher der Dauerspam kommen könnte sieht man in Deinem Codeausschnitt nicht. Das liegt aber sicher an Dir und nicht an der Socket-Klasse 😃

09.01.2012 - 19:16 Uhr

Ich verstehe generell nicht, wie man hier bei der ursprünglichen Beschreibung - 64 Eingänge auf deren Wert-Änderung man reagieren muss - überhaupt auf State-Machines kommt. Letztere machen meines Erachtens nach nur bei komplexen und stark verteilten Einzelzuständen Sinn. Hier würde ich einfach in regelmäßigen Abständen den aktuellen Zustand mit dem vorhergegangenen Zustand vergleichen und entsprechend auf Änderungen reagieren.

09.01.2012 - 19:03 Uhr

Da hast Du mehr reininterpretiert, als was ich gemeint habe. Um das zu praezisieren: Mit Funktionalitaet meine ich grundlegende Dinge, wie bspw. eine einfache Multiplikation etc, die auch voellig legitim ist, diese in einem Property unterzubringen.

Hallo DaMoe,

ich denke ich verstehe Dich schon, aber selbst eine einfache Multiplikation kann zu Verwirrung führen, wenn jemand das Property aufruft und nicht weiß (und es anhand des Property-Namens auch nicht erkennen kann), dass dort mit dem Feld-Wert noch etwas getan wird. Wenn ich private Properties in einem Code fände, in denen noch Felder manipuliert werden, würde ich das für einen sehr schlechten Programmierstil halten. Selbst bei öffentlichen Properties sollte man vorsichtig sein und keine Aktionen im Getter oder Setter vollziehen, die der Aufrufer nicht erahnen kann. Die einzigen Szenarien in denen ich befürworten würde, dass in einem Property mehr als nur eine Rückgabe bzw. eine Zuweisung geschieht sind

a) Der Property-Name drückt das, was als Ergebnis geliefert wird bzw. was mit der Eingabe geschieht aus.
Z.B.


public int MultiplicationResult
{
   get { return input1 * input2; }
}

In diesem Fall liefert das Property nur einen errechneten Wert abhängig von zuvor getätigten Eingaben, dient also als Abkürzung für eine voll ausprogrammierte Methode, während es aber gleichzeitig den Eigenschaften-Charakter behält.

b) Bei Standard-Implementierungen, die allgemein verbreitet und bekannt sind wie z.B. das Abfeuern eines NotifyPropertyChanged Ereignisses bei einem Binding-Property.

09.01.2012 - 16:56 Uhr

Sobald ich mehr "Funktionalitaet" benoetige, wie z.B. Lazy Loader, Kalkulationen etc. verwende ich private Properties.

Ich würde Private Properties nicht mal hier verwenden. Was passiert wenn Du mehr als eine "Funktionalität" auf einem Feld durchführen musst ? Dann läufst Du Gefahr, eine Funktionalität in einem Property "versteckt" zu haben und eine andere in einer privaten Methode.

Ich sehe keinen Sinn in der Verwendung von privaten Properties. Interne Funktionalität zur Manipulation von Feldern sollte in entsprechenden privaten Methoden mit sprechenden Namen realisiert werden, damit man beim Arbeiten an der Klasse schon am Methodennamen erkennen kann, welche Funktionalität sie realisiert. Ein privates Property MeinObjekt sagt dagegen nichts darüber aus, welche Funktionalität darin versteckt ist.

EDIT: Durch die Verwendung von privaten Properties statt privaten Feldern schützt man die Entwickler keinesfalls vor sich selbst, im Gegenteil, man verleitet sie dazu Properties auf die genannte Art und Weise als verkappte Methoden zu missbrauchen.

09.01.2012 - 16:43 Uhr

es gibt signifikante Unterschiede in der Länge des erforderlichen Quellcodes. Gerade wenn man alle möglichen Varianten mit normalen String-Operationen ausprogrammiert, wird es sehr länglich. In Regex erfordert das dagegen oft nur ein zusätzliches Zeichen, z.B. ? oder * oder |. Insofern ist Regex die deutlich bessere Wahl gegenüber StartsWith & Co.

Ein längerer Code ist nicht automatisch ein schlechterer Code, gerade im Hinblick auf die Lesbarkeit. Wenn ich irgendwo RegExp sehe kommt mir das Grausen, das erinnert mich immer an die kryptischen Perl-Scripts aus längst vergangenen Zeiten. Lambda Expressions sind genauso ein Murks, der nicht zur Lesbarkeit beigetragen hat. Ist aber nur meine Meinung...

27.12.2011 - 20:34 Uhr

Hiermit kannst jedes Dictionary easy serialisieren / deserialisieren:

ObjectSerializer

27.12.2011 - 20:30 Uhr

Ihr wollt aber nicht ernsthaft vorschlagen "mehrere Gigabyte"

  1. zu serialisieren
  2. noch über das Netzwerk zu jagen und dann
  3. dafür auch noch .NET Remoting zu verwenden und
  4. wieder zu deserialisieren

?

Wieviele Stunden soll denn der Benutzer bereit sein, auf die Daten zu warten ?
Da ist es meiner Meinung nach schneller, die Tabellen lieber 10 mal direkt neu zu laden...

23.12.2011 - 09:12 Uhr

Ich arbeite zwar nicht mit dem .NET Webbrowser Control, aber mit MSHTML und SHDocVW, wobei ich glaube, das .NET Webbrowser Control nutzt intern auch MSHTML bzw. SHDocVW.

Ich bin auf dasselbe Problem gestoßen wie Du - wenn eine Seite Frames mit src aus verschiedenen Domains beinhaltet, ist der Zugriff auf die Frames normalerweise nicht gestattet.

Ich habe aber einen Weg gefunden, das Ganz zu umgehen und zwar so:


public static class CrossDomainHelper
  {
    /// <summary>
    /// Returns the HTMLDocument object hostet by a specified frame element.
    /// If the passed IHTMLWindow2 instance is not a frame or a browser object, an invalid cast exception will be thrown.
    /// </summary>
    /// <param name="frame">IHTMLWindow2 instance wrapping up a HTMLFrameElement or a IHTMLWebBrowser2 instance.</param>
    /// <returns>The document hosted by the specified frame or browser object.</returns>
    public static IHTMLDocument2 GetCrossDomainDocumentFromFrame(IHTMLWindow2 frame)
    {
      int E_ACCESSDENIED = unchecked((int)0x80070005L);
      Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
      Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E");

      if (frame == null)
        return null;

      //Try if a cross domain conversion is necessary or if security setting don't restrict us from obtaining the frame document via the standard way...
      try
      {
        IHTMLDocument2 doc = frame.document;
        return doc;
      }
      catch (COMException comEx)
      {
        //In case a COMException is fired, check if it was a masked UnauthorizedAccess Exception
        if (comEx.ErrorCode != E_ACCESSDENIED)
        {
          //If it wasn't, some unexpected error occured -> return null in this case.
          return null;
        }
      }
      catch (System.UnauthorizedAccessException)
      {
        //Ignore UnathorizedAccessException, it only signals we have a cross domain access security restriction which we will deal with later.
      }
      catch
      {
        //any other unexpected error -> return null in this case
        return null;
      }

      //Let's deal with the cross domain restriction and retrieve the frame document using a COM service provider...
      try
      {
        // Convert IHTMLWindow2 to IWebBrowser2 using IServiceProvider and return the frame document if the COM extraction worked well.
        IServiceProvider sp = (IServiceProvider)frame;
        Object brws = null;
        sp.QueryService(ref IID_IWebBrowserApp, ref IID_IWebBrowser2, out brws);
        SHDocVw.IWebBrowser2 browser = (SHDocVw.IWebBrowser2)(brws);

        return (IHTMLDocument2)browser.Document;
      }
      catch
      {
        //If for whatever reason the COM extraction doesn't work, return null...
        return null;
      }

      return null;
    }
  }
  
  /// <summary>
  /// COM service provider marshalling...
  /// </summary>
  [ComImport(), ComVisible(true), Guid("6D5140C1-7436-11CE-8034-00AA006009FA"),
  InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
  public interface IServiceProvider
  {
    [return: MarshalAs(UnmanagedType.I4)]
    [PreserveSig]
    int QueryService(ref Guid guidService, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppvObject);
  }

Wie Du das jetzt genau auf das .NET Webbrowser Control übertragen kannst, weiß ich nicht - dazu hab ich es mir nicht lange genug angeschaut. Für meinen Zweck reicht die Funktionalität des .NET Controls nicht aus, weswegen ich dann bei den SHDocVW / MSHTML COM-Komponenten gelandet bin.

22.12.2011 - 17:32 Uhr

Muss es WinForms sein ? Mit WPF kannst Du die Breite der Buttons komfortabel an die Breite des Containers binden...

22.12.2011 - 16:01 Uhr

Hallo herbivore,

das hab ich schon fast befürchtet, ist ja irgendwie auch logisch. Gibt es denn außer der URL etwas Anderes, Kürzeres, über dass sich eine Webseite eindeutig identifizieren lässt ? Ich denke mal, wenn ich nur noch 4 Zeichen der URL berücksichtige, ist eine Überlappung zweier Websites zu wahrscheinlich.

Zur Erklärung des Hintergrunds: Ich muss HTML-Elemente (Buttons, Textboxen, Links usw.) wieder erkennen können, und das über mehrere verschiedene HTML-Dokumente in ggf. mehreren verschiedenen InternetExplorer Instanzen hinweg. Daher wollte ich mir eine ID zu jedem gefundenen Element erstellen, die abhängig ist von der Webseite, in der das Element vorkommt (daher die URL) und von anderen unveränderlichen Eigenschaften des Objektes.

Die Einschränkung ist, dass ich ein "Handle" vom Typ integer brauche, das liegt an einer Schnittstelle, die ich nicht beeinflussen kann.

Als unveränderliche Eigenschaften stehen mir drei Zahlen zur Verfügung, zwei davon innrhalb eines Wertebereiches von -2000 bis + 2000 und eine innerhalb eines Wertebereiches von 0 bis 10000. Mit diesen drei Zahlen ist das HTML Element eindeutig INNERHALB EINES HTML-Dokumentes beschrieben. D.h. ich muss zusätzlich noch eine Information mitkodieren, durch die sich dann die erzeugten IDs aus Webseite 1 von denen aus Webseite 2 unterscheiden.

Vielleicht hat ja jemand eine Idee dazu...

@m.knigge

Danke, werde ich mir mal anschauen...

22.12.2011 - 15:34 Uhr

Hallo gfoidl,

ich hab im Vorfeld bereits danach gesucht, aber nur Algorithmen gefunden, die mir ein byte[] zurück liefern, damit kann ich aber nichts anfangen, da ich den codierten Wert unbedingt als Integer brauche.

Wenn Du einen speziellen Hash-Algorithmus kennst, der mir das liefern kann, wäre ich dankbar für eine detailliertere Antwort.

22.12.2011 - 15:27 Uhr

Hallo zusammen,

kennt jemand einen (Standard-)Algorithmus der mir einen String von fester Länge (z.B. 8 Zeichen) auf einen eindeutigen Integer-Wert abbildet ?

Es ist dabei nicht nötig, später den String wieder reproduzieren zu können, lediglich die generierte ID vom Typ integer muss eindeutig sein. Es wäre auch wünschenswert, dass die erzeugte Integer-Zahl eine fixe Anzahl von Dezimalstellen hat, wobei ggf. mit Nullen aufgefüllt werden kann aber eine bestimmte Obergrenze nicht überschritten werden darf.

Beispiel :

String-Eingabe : www.mycsharp.de
Erzeugte ID (≤ 10 Dezimalstellen) : 1234567890

Mit einem long-Wert müsste es denke ich z.B. so gehen:


private static long UrlToLong(string url)
    {
      int initialLength = url.Length;
      long value = 0;

      int lastXCharacters = 8;
      if (lastXCharacters > url.Length)
        lastXCharacters = url.Length; //if the url has less than 8 characters, ignore the lower decimal positions (keep them at zero)

      //start with the last character in the url
      for (int i = 1; i <= lastXCharacters; i++)
      {
        double ascii = (double)((int)url[url.Length - i]);
        double exp = Math.Pow(256, 8 - i);
        value += ((long)ascii * (long)exp);
      }

      return value;      
    }

Ein Integer hat allerdings einen zu kleinen Wertebereich für die obige Methode, weshalb ich mich gefragt habe, ob es dafür einen fertigen Encoding-Algorithmus gibt.

22.12.2011 - 14:31 Uhr

Da gibt es sicher nicht "die" Patentlösung. Ich denke die Realisierung ist letztendlich Geschmackssache. Aus Sicht der OO würde ich aber nicht im Manager-Objekt die Events der Timer abonnieren, sondern vom Workerobjekt heraus ein eigenes Event definieren. Damit sind die Timer dann in der Worker-Klasse gekapselt und wenn Du irgendwann entscheidest, dass statt einem Timer etwas anderes verwendet werden soll, kannst Du das in der Workerklasse intern austuaschen, ohne dein Managerobjekt zusätzlich ändern zu müssen.

Zur Frage der Weiterleitung über die Eventargs, warum willst Du den Timer als Eventargs weitergeben ? Gib doch gleich die Queue als Eventargs mit, auf die sich der Timer bezieht, dann kannst Du gleich im Managerobjekt mit der Queue arbeiten und brauchst nicht noch einen weiteren Zugriff auf das Workerobjekt.

21.12.2011 - 09:45 Uhr

Die scrollbar-Problematik konnte ich gerade lösen.

Wen es interessiert: Wenn browser die SHDocVW.InternetExplorer Instanz ist, kriegt man die Scrollbar-Werte so:


HTMLDocument doc = (HTMLDocument)browser.Document;
HTMLHtmlElement html = (HTMLHtmlElement)doc.DocumentElement;
int scrollX = html.scrollLeft;
int scrollY = html.scrollTop;

Die Scrollbarwerte kommen dabei in falscher (negativer) Richtung zurück, d.h. man muss die Scrollbarwerte von der Koordinate abziehen anstatt sie zu addieren.

Für den Border hab ich immer noch nichts gefunden...

20.12.2011 - 17:30 Uhr

Du könntest auch noch bei jedem gefunden Directory (falls es doch mehrere gibt) mit Directory.GetFiles() prüfen ob deine key3.db und signons.sqlite Dateien in dem jeweiligen Verzeichnis liegen. Wenn Du mehr als ein Verzeichnis findest, in dem diese Dateien liegen, würde ich über einen Message-Dialog den Benutzer auswählen lassen, für welches der Verzeichnisse er/sie das Backup ausführen möchte.

20.12.2011 - 17:19 Uhr

Hallo zusammen,

Ich nutze SHDocVW.dll und mshtml.dll um eine InternetExplorer Anwendung zu automatisieren. Soweit klappt es ganz gut, aber ich habe zwei Probleme, die mich in den Wahnsinn treiben, weil ich keine Dokumentation dazu finde.

Zum Einen brauche ich den aktuellen Ausschlag (integer-Wert) der Scrollbars (horizontal u. vertikal) eines Internet Explorer-Tabs, wobei der Tab vom Typ SHDocVW.IWebBrowser2 bzw. SHDocVW.InternetExplorer ist. Über beide Typen finde ich keine Möglichkeit, die Scrollbars auszulesen. Gibt es vielleicht ein weiteres Interface, in das ich das Tab-Objekt casten kann, welches mir dann den Zugriff auf die Scrollbars erlaubt ? Ich finde dazu nichts in der SHDocVW Referenz...

Das zweite Problem ist, dass ich beim Berechnen der globalen Desktop-Position eines Webcontrols im automatisierten HTML-Dokument immer einen Versatz von 3 Pixeln in x- und y-Richtung habe. Ich vermute, dass es sich dabei um die Borderwidth des Tabs handelt. Auch diesen müsste ich also irgendwie auslesen können, da ich nur ungern hartcodiert immer +3 rechnen möchte.

Ich hoffe, es hat schonmal jemand mit SHDocVW und MSHTML gearbeitet und kann mir irgendwie weiter helfen.

Die .NET internen Internetexplorer Controls kann ich leider nicht nutzen, da mein Tool imstande sein muss, sich mit einer externen Internetexplorer-Instanz zu verbinden.

Danke...

Edit: Tippfehler beseitigt.

20.12.2011 - 15:40 Uhr

Fehler in XML-Dokument klingt so als ob der Webservice schon Mist zurück gibt. Kann man die Webservicemethode denn in irgendeiner anderen Umgebung konsumieren, bzw. ist es sicher, dass der Webservice überhaupt korrekt funktioniert ?

Kannst Du bei der Exception Fehler in XML-Dokument in der inner Exception nachschauen, ob dort ein detaillierterer Fehler angegeben ist ?

Ich sehe nicht, warum es einen Fehler geben sollte, nur weil es ein PHP-Webservice ist. Gerade um technologieunabhängig zu sein führt man ja eine Zwischenebene wie z.B. SOAP ein.

19.12.2011 - 18:04 Uhr

Wie bindest Du denn den Webservice in dein C# Projekt ein ? Über einen Webverweis ?

Wenn ja, dann stelle mal sicher, dass Du auch die Player-Klasse aus den Proxy-Klassen (die beim Hinzufügen des Webverweises erzeugt werden) benutzt und nicht eine andere (lokale) Player-Klasse, die nur gleich aufgebaut ist.

Du kannst Dir auch mal ein object zurückgeben lassen


object p = myWS.webservicemethode(param); 

und dann per p.GetType().ToString() prüfen, auf welchen Rückgabetyp (in welchem Namespace, in welcher Assembly) sich die Webservice-Methode bezieht.

14.12.2011 - 18:41 Uhr

Wenn ich dich richtig verstehe, willst Du am Ende ein Dictionary haben, in dem die Key/Value Paare aus der xml Datei gespeichert werden ? Wenn Deine Methode ein Objekt vom Typ Player zurück gibt dann musst Du das natürlich erstmal so umsetzen...


Player p = myWS.webservicemethode(param);

Jetzt weiß ich eben immer noch nicht genau, wie deine Player Klasse aufgebaut ist, aber nach Deiner Beschreibung solltest Du das jetzt so in ein Dictionary kriegen:


Dictionary d = new Dictionary<string, object>();
d.Add("NameField1", p.NameField1);
d.Add("NameField2", p.NameField2);
...

NameField1, 2 usw. musst Du natürlich noch durch die echten Namen ersetzen. Falls die Felder nicht public sind, rufe stattdessen eben die getter-Methode auf.

09.12.2011 - 09:34 Uhr

Das klingt so also ob die MEthode myWS.webservicemethode() ein Array von XmlNodes zurückliefert. In dem Falls solltest Du Dir ein C# XML Tutorial suchen, in welchem Du Dir abschauen kannst, wie man die Infos aus den XMLNodes ausliest. Wie ist denn Deine Player-Klasse aufgebaut ?

08.12.2011 - 10:54 Uhr

Soetwas wie Dictionary.FillFromWebservice o.Ä. gibt es nicht. Du musst die Daten, die vom Webservice ankommen selbst mit Add() in das Dictionary schaufeln.

Falls die Daten als object Array (object[]) ankommen, tut es vielleicht statt dem Dictionary auch eine List<>.


object[] data = GetDataFromWebservice();
List<object> myList = new List(data);
07.12.2011 - 12:58 Uhr

Mit TenderTypeCode hat die Fehlermeldung nichts zu tun. Eigentlich steht in der Fehlermeldung genau, was das Problem ist:

Der Zielnamespace einer lokalen oder globalen Attributsdeklaration darf nicht mit
>
übereinstimmen.

Zielnamespace auf englisch = targetNamespace

Diese Erkenntnis noch auf folgende Zeile anwenden

  
<xs:schema xmlns="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.w3.org/2001/XMLSchema-instance">  
  

Grüße
Lynix

06.12.2011 - 16:39 Uhr

Hallo mexxchen,

ich weiß nicht ob es daran liegt, aber probier mal GetWindowThreadProcessId so einzubinden:


[DllImport("user32.dll")]
    private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);

So nutze ich es in meinem Projekt und es funktioniert bisher eigentlich mit jedem Windowhandle.

Was bedeutet, Du bekommst "nicht immer das gewünschte Handle" ? Bekommst Du garkein Handle oder trifft nur manchmal Folgendes nicht zu:


if (processId == Int32.Parse(GetCurrentProcessId()))

?

P.S.: Wenn Du die Position des gesuchten Window auf dem Desktop kennst, kannst Du statt EnumWindows auch das hier verwenden:


[DllImport("user32.dll")]
private static extern IntPtr WindowFromPoint(int xPoint, int yPoint);

05.12.2011 - 16:09 Uhr

Kannst Du nicht beim Start jeder Einzelproduktion eine ID der Hauptproduktion zu der sie gehört mitgeben ? Dann kannst Du doch über ein geeignetes Event abfangen wenn eine Einzelproduktion beendet wurde und dann prüfen, ob alle anderen mit derselben Hauptproduktion-ID auch schon beendet sind. Die Gruppierung von Einzelproduktionen zu Hauptproduktion würdest Du dann schon machen, bevor die Produktion beginnt, und müsstest dich dann nicht um das Zeitproblem kümmern.

Nur so eine Idee, ich weiß nicht ob das auf Dein Problem anwendbar ist, dazu sind es wie schon gesagt wurde, viel zu wenig Informationen.

01.12.2011 - 19:08 Uhr

Hallo herbivore,

ich bin deiner Anregung gefolgt und habe eine Zahlencodierung aus unveränderbaren Properties des HTML-Buttons programmiert. Die dazu geschriebene Methode liefert mir 24-stellige Zahlen, wobei ich diese wie folgt aufgebaut habe:

  • 1023 bis 1020 repräsentieren den Betrag der Eigenschaft "Left"
  • 1019 bis 1016 repräsentieren die Betrag der Eigenschaft "Top"
  • 1015 bis 1012 repräsentieren den SourceIndex des jeweiligen HTML Elements innerhalb seines Dokumentes
  • 1011 bis 100 repräsentieren die letzten Zeichen der url-Eigenschaft des Dokuments in dem das HTML Element vorkommt.

Ich habe es mal testweise über eine HTML-Anwendung mit ca. 200 Unterseiten und verschachtelten Frame-Dokumenten laufen lassen und bisher jedes Element über die so erzeugte "ID" wiederfinden können.

Wenn jemand noch eine bessere Idee hat, wie man so ein Problem (also Objektinstanz auf eine eindeutige ID abbilden) generell bzw. wiederverwendbar lösen könnte, wäre ich trotzdem daran interessiert.

30.11.2011 - 18:20 Uhr

Hallo zusammen,

folgende Situation:

Ich bekomme über eine COM Komponente zur Laufzeit verschiedene Objektinstanzen zurück geliefert. Bei den Objekten handelt es sich um HTML-Controls die sich in einem in irgendeiner geöffneten IE Instanz gehosteten HTML-Dokument befinden.

Für jedes dieser Objekte lege ich eine Instanz einer Wrapper-Klasse an, die das COM Objekt intern hält und verschiedene Operationen darauf ausführt. Letzteres dauert teilweise relativ lange, deswegen würde ich gerne erreichen, dass ich nicht bei jedem erneuten Zugriff, bei dem wieder dasselbe HTML-Control betroffen ist, nochmal diesen Wrapper-Prozess durchlaufen muss.

Daher wollte ich mir alle einmal erzeugten Wrapper-Objekte an geeigneter Stelle in einem statischen Dictionary halten und bei jedem Zugriff erstmal Testen, ob zu dem gerade behandelten HTML-Control schon ein Wrapper existiert. Ich will also sozusagen eine Art Cache für bereits gewrappte Objekte realisieren.

Um von Außen testen zu können, ob es bereits einen Wrapper für ein HTML-Control gibt, habe ich in der Wrapper Klasse die MEthode GetHashCode() überschrieben, und zwar so, dass sie einfach mWrappedObject.GetHashCode(), also den Hashcode des intern verwalteten Objektes zurück liefert.

Täte das funktionieren tun, könnte ich diesen Hashcode als Key für mein statisches Dictionary nehmen und könnte dann prüfen


if(sAllWrappedObjects.ContainsKey(htmlControl.GetHashcode()))
  return sAllWrappedObjects[htmlControl.GetHashcode())];
else
{
   Wrapper w = new Wrapper(htmlControl); //wait 5 minutes
   sAllWrappedObjects.Add(htmlControl.GetHashcode(), w);
   return w;
}

Nun schien es zunächst zu funktionieren, bis mir sporadisch das Ganze mit einer Exception um die Ohren fliegt. Nach etwas Debugging ist mir aufgefallen, dass folgendes Problem besteht:

Wenn ich ein HTML-Button Objekt über die COM-Schnittstelle abfrage und darauf GetHashCode() ausführe bekomme ich z.B. 1 zurück geliefert und der Hashcode bleibt auch 1 für dieses Objekt. Wenn ich aber jetzt über die COM Schnittstelle vom haargenau gleichen HTML-Button nochmal ein Objekt abfrage, liefert mir GetHashcode aber jetzt einen anderen Wert, z.B. 2.

D.h. obwohl beide Objekte eigentlich denselben Button repräsentieren, geben sie unterschiedliche Hashcodes zurück. Somit bringt mich dieser Ansatz nicht weiter.

Was ich daher jetzt suche, wäre eine genereller Ansatz, wie ich ein Objekt auf eine eindeutige Zahl abbilden kann. D.h. ich brauche die Möglichkeit die Identität eines Objektes abzufragen. Eine Idee wäre z.B. aus allen PropertyWerten eine eindeutge Zahl zu generieren. Das hilft mir aber auch nicht, da sich die Propertywerte innerhalb der Anwendung ändern können (und sollen).

Ich habe hier den ganzen Hintergrund beschrieben, da ich momentan nicht sicher bin, was ich eigentlich brauche. Ich will die Objekte nicht auf Wertgleichheit (im Sinne von Property-Werten) überprüfen, da der Wert sich ständig ändern kann. Ich will aber eigentlich auch keine Referenzgleichheit abprüfen, da sich zwei unterschiedliche Objektreferenzen auf dasselbe Low-Level Objekt (HTML-Button) beziehen können.

Wäre für jegliche Tipps dankbar.

25.11.2011 - 11:43 Uhr

Diese Seite, die auch über google gefunden habe, beschreibt aber leider auch nur, was Ko- / Kontravarianz ist, und nicht, wie ich sie für meine Problemstellung implementieren kann.

Ich denke, der Thread kann zu gemacht werden - es scheint wohl eher darum zu gehen, dass ich hier rechtfertigen soll, warum ich den Thread geöffnet habe, als darum, eine Lösung für das Problem zu finden. Das hilft mir aber nicht, und sonst sicher auch niemandem, der in diesem Forum nach Lösungen sucht.

25.11.2011 - 10:31 Uhr

Hallo herbivore,

sorry, aber die Aussage hilft mir nicht weiter. Das ich Kontravaianz brauche ist mir klar, nicht jedoch, wie ich diese realisieren kann. Könntest Du mir dazu ein Beispiel geben ?

Danke...

25.11.2011 - 09:09 Uhr

GUIObject ist ja schon die abstakte Basisklasse, inwiefern würde es mir weiterhelfen noch ein Interface darüber zu setzen ?

24.11.2011 - 17:21 Uhr

Folgende Situation:

Ich möchte eine Plugin-Struktur realisieren, d.h. ich habe so etwas wie einen Kernel, der über Schnittstellen vorgibt, was die einzelnen Plugins realisieren müssen, so weit auch noch kein Problem.

In dem "Kernel" gibt es Objekte (GUI-Elemente) mit denen gearbeitet wird. Was damit gearbeitet wird, entscheidet sich in einer GUIAccess Klasse.

Beide Konzepte sind in Form von abstrakten Basisklassen realisert. Also eine abstrakte GUIObject Klasse und eine abstracte GUIAccess Klasse. Die in diesen Schnittstellen definierten Funktionen müssen von Plugins realisiert werden.

Das konkrete Problem, an dem ich gerade gedanklich hänge ist Folgendes:

In der abstrakten GUIAccess Klasse gibt es z.B. Methoden wie

abstract void DoSomethingWithGUIObject(GUIObject obj);

Wenn ich nun ein Plugin entwickle, habe ich eine konkrete Implementierung von GUIObject, von mir aus Win32GUIObject und eine konkrete Implementierung von GUIAccess, sagen wir Win32GUIAccess.

Obige Methode kann ich also auch in Win32GUIAccess nur als

override void DoSomethingWithGUIObject(GUIObject obj) 

implementieren.

Was mir daran nicht gefällt ist, dass als Parameter in die konkrete Realisierung jetzt theoretisch auch ein anderes, von GUIObject abgeleitetes Objekt, reingegeben werden kann.

Win32GUIAccess soll sich aber nur um Win32GUIObject Instanzen kümmern. Klar kann ich jetzt intern den Check machen

if(obj is Win32GUIObject)
//DoSomething
else
throw new ApplicationException(...)

Das erscheint mir aber sehr unsauber, da der Aufrufer der abgeleiteten Klasse ja durch die Signatur nur einen Parameter vom Typ GUIObject sieht und sicher auch erwartet, dass es dann auch ein beliebiges GUIObject sein darf.

Vielleicht starre ich jetzt einfach nur schon zu lange auf den Monitor um die vermutlich leichte Lösung zu sehen, aber gerade im Moment fällt mir keine vernünftige Anpassung des Klassenkonzepts ein.

Vielleicht hat ja jemand eine Idee / Anregung zu dem Problem.

Danke & Grüße
Lynix

09.11.2011 - 12:52 Uhr

@Frage 1: statische Klasse und Singleton sind definitiv nicht der Standard. Guck dir mal
>
an, dort findest du eine nette Übersicht über die Möglichkeiten die anschließend auch kommentiert wurde.

Hallo gfoidl,

der Link hat mir für Frage 1 schonmal weiter geholfen, danke. Aber eine Nachfrage habe ich noch zum Verständnis. Bei der in dem Artikel beschriebenen Option 4

  
<UserControl ...>  
    <UserControl.DataContext>  
        <local:CalculatorViewModel />  
    </UserControl.DataContext>  
</UserControl>  
  

-> würde das bedeuten, dass CalculatorViewModel eine statische Klasse sein muss ? Oder wird durch diese XAML Deklaration implizit eine Instanz von CalculatorViewModel erzeugt auf die sich dann die weiteren Bindings beziehen ?

08.11.2011 - 22:43 Uhr

Hallo zusammen,

ich bin gerade dabei mich mit WPF zu beschäftigen, und versuche gerade im Hinblick auf das MVVM Muster eine schöne "Blueprint"-Projektstruktur zu erstellen.

Ich gehe dabei von einem simplen (einzelnen) WPFApplication Projekt aus, in dem ich drei Namespaces vorsehe : MyApp.View MyApp.ViewModel und MyApp.Model

Für ein fiktives Window "Window1" welches ich im MyApp.View Namespace ablege, würde ich jetzt gerne eine Klasse Window1_VM anlegen, in dem ich alle Properties, die Window1 per Databinding konsumiert und alle für Window1 relevanten Custom Commands implementieren will.

Frage 1:

Sehe ich es richtig, dass ich im Window1 Codebehind dann eine Instanz von Window1_VM anlegen muss, um über XAML auf die Properties binden zu können ?
Falls ja, ist doch eigentlich die Entkopplung von View und ViewModel gleich schon dahin, oder ?

Als Alternative ist mir noch die Idee gekommen, Window1_VM gleich als statische Klasse zu realisieren, dann kann ich aber das nichtstatische NotifyPropertyChanged Event aus dem INotifyPropertyChanged interface nicht mehr nutzen, und das Binding taugt nicht mehr wirklich.

Es würde sich natürlich noch über eine Realisierung von Window1_VM als Singleton lösen / umgehen lassen, aber das kann doch eigentlich nicht der Standard sein oder ?

Wäre nett, wenn hier jemand etwas Licht ins Dunkel bringen könnte...

Frage 2:

Ich bin bisher davon ausgegangen, ich das MVVM gewinnbringend nutzen kann, um die Ebene View von der Ebene Model möglichst unabhängig zu halten. Wenn ich mir jetzt eine einfache Anwendung vorstelle, die nur aus einer Datenbank eine Liste von Datensätzen auslesen soll und diese Liste darstellen soll, wie würde man hier am Besten vorgehen ?

Wenn ich mir nun ein WPF Window mit einem Datagrid anlege und die Datasource auf ein DataSet im ViewModel binde, dann habe ich doch durch die Entscheidung, auf dem Window ein Datagrid zu benutzen, eigentlich schon die Ebene ViewModel (muss ein Dataset bereitstellen) und die Ebene Model (muss beim Zugriff auf die Datenbank ein Dataset zurückgeben) schon gleich mit festgelegt, oder ?

Wenn ich nun übermorgen entscheide, dass mir eine ListView viel besser gefällt als ein Datagrid, dann wäre es ja notwendig auch das ViewModel anzupassen, damit es mir die Daten in einem für eine Listview angenehmeren Format als ein Dataset zur Verfügung stellt...

Wo liegt mein Denkfehler ?

07.11.2011 - 11:36 Uhr

Ah, habs jetzt verstanden und ausprobiert. Funktioniert, danke Dir !

05.11.2011 - 18:45 Uhr

Hallo herbivore,

danke Dir für die Antwort, aber so richtig hilft mir das nicht. Eine IHTMLElementCollection habe ich an der Stelle nicht. Der erste Zugriffslevel ist das HTMLDocument, wenn ich da über doc.All.items über einen festen Namen auf ein Objekt zugreife, erhalte ich ein IHTMLElement zurück. Dieses hat wieder eine "childs" Eigenschaft bei der ich wieder nur über name und index auf Kindknoten zugreifen kann.

04.11.2011 - 19:19 Uhr

Ich sehe keinen Vorteil darin, die fertigen Proxy-Objekte die ganze Zeit in einer Liste zu halten. Und nur um mal ein Singleton-Pattern umgesetzt zu haben sollte man sowas auch nicht machen. Es geht nicht darum möglichst Komplexität in einen einfachen Sachverhalt zu bringen.

Konkret würde ich mir nur die Informationen zu den verfügbaren Proxies merken und die Proxy-Objekte selbst erst dann anlegen, wenn sie gebraucht werden, und wieder wegschmeißen, wenn sie nicht mehr gebraucht werden.

04.11.2011 - 14:51 Uhr

Hallo zusammen,

ich versuche auf Basis von MSHTML und MS Internet Controls (beide eingebunden als COM über die mshtml.dll bzw. SHDocVw.dll) eine Art Testautomatisierung für Webseiten zu entwickeln.

Dabei verbinde ich mich zu einer laufenden Internet Explorer Instanz und kann dann über die aus MSHTML bereitgestellten Interfaces mit einzelnen Webcontrols interagieren. Grundsätzlich funktioniert das auch ganz gut, aber ich habe das Problem, dass ich gerne ein ganz bestimmtes Control auswählen würde und dabei hapert es.

Mal etwas Code:


ShellWindows sw = new ShellWindowsClass();
InternetExplorer ie = null;

foreach(InternetExplorer exp in sw) 
{
   ie = exp;
   if (ie.Document.GetType().Name.Contains("HTML"))
   break;
}

HTMLDocument doc = ie.Document as mshtml.HTMLDocument;

So weit so gut, ich kann jetzt über die childNodes des HTMLDocument Objektes durch die einzelnen Objekte wie Divs, Buttons, Textbereiche etc. iterieren.


IHTMLDOMChildrenCollection docChilds = (IHTMLDOMChildrenCollection)doc.childNodes;

foreach (IHTMLDOMNode node in docChilds)
{
  //do something
}

Falls ein spezielles Objekt einen Namen hat und ich diesen Namen kenne, kann ich auch direkt darauf zugreifen, indem ich die All Eigenschaft des Dokumentes nutze:


object a = null;
object b = null;
object c = null;
object d = null;
ie.Navigate(@"http:\\www.google.de", ref a, ref b, ref c, ref d);

HTMLInputElement txtBox = (HTMLInputElement)doc.all.item("q", 0);
txtBox.value = "Microsoft";

HTMLInputElement btn = (HTMLInputElement)doc.all.item("btnI", 0);
btn.click();

Da niemand den Entwickler der Website zwingt, jedem Element einen Namen zu geben, gibt es sehr viele Elemente ohne Namen, auf die ich folglich auch nicht direkt zugreifen kann.

Was ich bräuchte wäre eine Möglichkeit z.B. die 5. Textbox im 3.Div Tag auszuwählen, möglichst ohne, dass ich alle Childnodes des Document durchlaufen muss (das werden sehr schnell einige 10.000) und womöglich noch manuell mitzählen muss, im wieivielten Div-Block und am wievielten Button ich gerade bin.

Ich habe jetzt gesehen, dass jedes Element noch weitere Properties wie UniqueNumber, UniqueID und SourceIndex mitbringt. UniqueNumber und UniqueID sind unbrauchbar, da diese bei jedem Neustart des IE neu vergeben werden. Der SourceIndex wird einach hochgezählt, also das erste <html> Tag bekommt Index 1, das nächste Tag 2 usw.
Damit könnte man denke ich etwas anfangen, aber ich habe leider keinen Weg gefunden, über den SourceIndex das entsprechende Element abzufragen.

HTMLDocument.All.Item() verlagnt immer zwei Parameter Name und Index 😦

Hat jemand damit schonmal gearbeitet und kann mir vielleicht grundsätzliche Tips zu Möglichkeiten der Navigation innerhalb eines Dokumentes geben ?

Gleich vorne weg : Das Webbrowser Control nd die HttpDocument Klasse aus dem Framework kann ich nicht nutzen, da die Software in der Lage sein soll, sich mit einem beliebigen, bereits laufenden IE zu verbinden. Ich kann also die Webseite nicht selbst in einem Webbrowser Control öffnen 😦

Danke schonmal...

27.10.2011 - 09:07 Uhr

Hallo zusammen,

gibt es eine einfach Möglichkeit, die Mehrfachausführung eines Eventtriggers zu verhindern ?

Ich habe beispielsweise ein Storyboard mit verschiedenen Animationen an den Eventtrigger Button.Click gebunden. Wenn die Animation jetzt bereits läuft und ich den Button nochmals klicke, startet die Animation mittendrin von vorne.

Ich habe bisher ein Beispiel gefunden, bei dem die zweite Animation (also die beim 2. Klick ausgeführt wird) so initialisiert wird, dass sie genau da anfängt, wo die erste gerade war. Dadurch sieht man optisch nicht, dass eigentlich gerade 2 Animationen ablaufen. Das hilft mir in meinem konkreten Fall aber nicht weiter. Bei mir wird ein Image-Objekt mit zwei Buttons über den Bildschirm bewegt, wobei sich bei jedem Buttonclick aber die Source des Images ändert. Daher bringt es mir nichts, wenn die Animation zwar scheinbar flüssig weiter läuft, sich aber mittendrin das Bild ändert.

Kann man irgendwie die Mehrfachausführung dieses Storyboards sperren ? So dass der zweite Eventtrigger erst ausgelöst werden kann, wenn das Storyboard hinter dem ersten abgearbeitet ist ?

Danke...

16.10.2011 - 11:00 Uhr

Vielen Dank, WatiN sieht vielversprechend aus.