Laden...

Forenbeiträge von inflames2k Ingesamt 2.298 Beiträge

20.08.2018 - 08:15 Uhr

Hast du denn schon einmal mit dem Debugger geschaut was da los ist?

27.07.2018 - 15:16 Uhr

Impersonation an sich ist eigentlich schon eine relativ einfache herangehensweise um sich an anderen Rechnern anzumelden. Aber: Spricht etwas dagegen einfach einen FTP-Server zu verwenden?

22.07.2018 - 11:12 Uhr

Hast du den Zugriff per TR64-API in der Box aktiviert?

Ansonsten, falls du dir bei Github mal den Source gezogen hast versuche mal in den Control-Pfaden "/upnp/" durch "/igdunpn/" zu ändern. - Eventuell funktionieren damit die Zugriffe, habe ich gerade im Internet entdeckt. - Sicher bin ich allerdings nicht, habe auch keine Cable mit der ich das testen kann.

Sollte es der Fall sein, überlege ich mir noch etwas wie man den Control-Pfad dynamischer gestalten kann.

Ich werde mich nun erst mal an das versprochene aufräumen machen.

18.07.2018 - 16:54 Uhr

Funktionieren denn andere Schnittstellen oder ist nur die Schnittstelle betroffen?

Probier mal folgendes:


DeviceLocator locator = new DeviceLocator();
var devices = await locater.DiscoverAsync();
if(devices.Count() > 0)
{
    var device = devices.First();
    ConnectionSettings settings = new ConnectionSettings()
    {
       UserName = "inflames2k";
       Password = "secret";
    };

    var client = await device.GetServiceClient<DeviceConfigClient>(settings);
    await client.RebootAsync();
}

Möglicherweise passt deine Base-Url nicht. Das könnten wir auf diesem Weg ausschließen, da die BaseUrl hier automatisch ermittelt wird.

18.07.2018 - 16:48 Uhr

Der ConnectionState kommt von der Box. - Das heißt für mich, das Tool bekommt gar keine Verbindung zur Box.

Was steht denn als Fehlermeldung in dem Fehler? Also ohne Stacktrace. Das Device Name etc. ausgefüllt werden, heißt für mich das die Verbindung grundsätzlich erst einmal funktioniert. Problem scheint also an anderer Stelle zu liegen.

Kannst du mal einen Screenshot mit anhängen?

12.07.2018 - 16:25 Uhr

Naja, werde jetzt sowieso demnächst den Dev-Branch (vermutlich am Wochende) bereinigen, in den Master übertragen und ab dann mit dem von dir beschriebenen Weg fortfahren. - Ich hoffe, du kannst bis dahin noch warten.

Die ganzen AVM-spezifischen Schnittstellen werde ich dann wohl sowieso erstmal wieder raus nehmen und an späterer Stelle wieder einbauen. So dass in der nächsten Version dann erstmal die ganzen WANDevice- und LANDevice Services sauber verfügbar sind.

Die Services wie z.B. das Telefonbuch würde ich dann über den von dir beschriebenen Weg (die Feature-Branches) hinzufügen.

12.07.2018 - 15:55 Uhr

Alles klar, achte aber mit drauf, dass ich ja schon wieder an der nächsten Version arbeite (Development branch). Dort habe ich mir automatisch die "Proxies" generieren lassen und muss dies noch ein wenig Anpassen (doppelte Klassen etc. entfernen). Nicht das wir dann am Ende 2 Zweige haben, die nicht mehr kompatibel sind beim Merge vom Develop zum Master.

PS: Die nächste Version unterscheidet dann zwischen den IGD-Services und den durch AVM im TR064 abgelegten Services. - So können dann unabhängig voneinander die IGD bzw. TR064 Services verwendet werden.

12.07.2018 - 15:42 Uhr

Wenn nichts hilft, nimm doch die Differenz zwischen dem Wert und dem letzten Wert für das verschieben statts fix 1.

16.06.2018 - 17:37 Uhr

Hallo,

ich habe eine neue Version der API veröffentlicht. - In der aktuellen Version wurden einige Umstrukturierungen innerhalb der API vorgenommen. Fehlerhafte Schnittstellen wurden korrigiert und neue Schnittstellen hinzugefügt.

Um den Konfigurationsaufwand auf die Nutzerdaten zu beschränken habe ich einen DeviceLocator implementiert. Dieser sucht per UPnP nach Fritzboxen im Netz und liefert diese als FritzDevice-Objekte zurück. - Auf die bereitgestellten Service-Clients kann dann durch die Methode "GetServiceClient" zugegriffen werden. - Die Methode nimmt die Authentifizierungsinformationen entgegen. - Die Angabe der Base URL ist bei Verwendung der FritzDevice-Klasse in Verbindung mit dem DeviceLocator nicht notwendig. - Lediglich Timeout, Nutzername und Passwort müssen gesetzt werden.

@Abt: Aufgrund von mir durchgeführter Anpassungen würde ich dich gern mal bitten, die API noch einmal zu testen. Möglicherweise lag hier doch ein Fehler meinerseits vor.

06.06.2018 - 10:38 Uhr

Dachte es gäbe eventuell die Möglichkeit noch irgendwie einen eigenen Scope einzuführen. - Aber gut, werde dann mal schauen das ich etwas brauchbares zusammen bekomme.

06.06.2018 - 09:51 Uhr

Hallo,

wir entwickeln gerade eine Anwendung für einen neuen Kunden. - Nun sind wir auf das Problem gestoßen, dass wir Einstellungen speichern müssen. - Dafür würde ich gerne das Konfigurationsmodell nutzen.

Nun unterscheidet die Settings-Klasse ja zwischen AppSettings und UserSettings. - Ist es möglich UserSettings unter C:\Users\Default\AppData\Local ablegen zu lassen statt unter dem spezifischen Benutzer und von dort aus auch wieder zu laden?

04.06.2018 - 10:49 Uhr

Du musst Methoden überhaupt nicht statisch erzeugen. - Die Program-Klasse ist statisch, da dies die Einstiegsklasse für das Programm ist (Gilt übrigens auch bei Forms-Apps). Für statische Klassen gilt die Regel, das alle Member statisch sein müssen. Erstellst du eine Klasse, die die Programmaufgaben übernimmt, kannst du diese einfach in Main als Instanz erzeugen und aufrufen. - Die Methoden der Klasse können und sollten dann alle non-static sein.

Beispiel:


public class MyWorkerClass
{
      public void DoWork()
      {
             Console.WriteLine("1 - Mitarbeiterverwaltung");
             Console.WriteLine("2 - Kundenverwaltung");

             var input = Console.ReadLine();
             if(input == "1")
                  this.HandleEmployees();
             else if(input == "2")
                  this.HandleCustomers();
      }

      private void HandleEmployees()
      {
            EmployeeManager manager = new EmployeeManager();
            manager.Handle();
      }

      private void HandleCustomers()
      {
            CustomerManager manager = new CustomerManager();
            manager.Handle();
      }
}

static class Program
{
        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
            MyWorkerClass worker = new MyWorkerClass();
            worker.DoWork();
        }
}

01.06.2018 - 16:18 Uhr

Hallo Tossi65,

aufbauend auf meinen Vorredner der Tipp: Merke dir, welche Punkte du gezeichnet hast und speichere die Auflistung der Koordinaten weg.- Beim Laden zeichnest du die Punkte einfach wieder neu.

Ich würde das in etwa wie folgt aufbauen (GraphicCanvas ist übrigens die Basis):


 /// <summary>
    /// base class for graphical objects
    /// </summary>
    public abstract class GraphicObject
    {
        /// <summary>
        /// gets or sets the line color
        /// </summary>
        public Color Color { get; set; }

        /// <summary>
        /// Method to draw the graphic
        /// </summary>
        /// <param name="graphics">the graphics</param>
        public abstract void Draw(Graphics graphics);
    }

 /// <summary>
    /// Line object
    /// </summary>
    public class LineObject : GraphicObject
    {
        /// <summary>
        /// Gets or sets the start point
        /// </summary>
        public Point StartPoint { get; set; }

        /// <summary>
        /// Gets or sets the end point
        /// </summary>
        public Point EndPoint { get; set; }
        public LineObject(Color linecolor, Point startPoint, Point endPoint)
        {
            base.Color = linecolor;

            this.StartPoint = startPoint;
            this.EndPoint = EndPoint;
        }

        /// <summary>
        /// drawing method
        /// </summary>
        /// <param name="graphics">the graphics</param>
        public override void Draw(Graphics graphics)
        {
            using (Pen pen = new Pen(this.Color))
            {
                graphics.DrawLine(pen, this.StartPoint, this.EndPoint);
            }
        }
    }

 /// <summary>
    /// canvas
    /// </summary>
    public class GraphicCanvas
    {
        /// <summary>
        /// the grafical objects
        /// </summary>
        public List<GraphicObject> GraphicObjects { get; set; } = new List<GraphicObject>();

        /// <summary>
        /// Method to add a graphical object
        /// </summary>
        /// <param name="graphic"></param>
        public void AddGraphicObject(GraphicObject graphic)
        {
            this.GraphicObjects.Add(graphic);
        }

        /// <summary>
        /// Method to remove
        /// </summary>
        /// <param name="graphic"></param>
        public void RemoveGraphicObject(GraphicObject graphic)
        {
            this.GraphicObjects.Remove(graphic);
        }

        /// <summary>
        /// method to draw
        /// </summary>
        /// <param name="graphics"></param>
        public void Draw(Graphics graphics)
        {
            foreach (GraphicObject graph in this.GraphicObjects)
                graph.Draw(graphics);
        }

        /// <summary>
        /// Method to save
        /// </summary>
        /// <param name="fileName"></param>
        public void Save(string fileName)
        {
            using (Stream fileStream = File.Create(fileName))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(GraphicCanvas));
                serializer.Serialize(fileStream, this);
            }
        }

        /// <summary>
        /// method to load canvas
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static GraphicCanvas Load(string fileName)
        {
            using (Stream fileStream = File.OpenRead(fileName))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(GraphicCanvas));
                return (GraphicCanvas)serializer.Deserialize(fileStream);
            }
        }
    }

ACHTUNG: Das ganze ist ungetestet und nur eben dahin geschrieben!

25.05.2018 - 07:20 Uhr

Hallo,

den Anwendungstitel habe ich korrigiert und ins englische überführt. - Sieht schon merkwürdig aus, wenn alles englisch ist außer der Titel.

03.05.2018 - 08:09 Uhr

Hallo,

grundsätzlich zum Abspielen von Musik kannst du ja mal meinen geposteten Code im Beitrag Irrklang spielt keinen Ton ab prüfen ob dieser funktioniert. Würde mich aber erst einmal wundern, wenn so viel geändert wäre, dass der nicht mehr funktioniert.

EDIT: Beachte auch die ersten Aussagen im Thread. - Die könnten schon des Rätsels Lösung sein, warum du keinen Ton erhältst.

19.04.2018 - 08:23 Uhr

Hallo,

es existieren keine "Spalten" in dem Sinne aus denen die beiden Ausgabeparameter generiert werden. Das heißt, es wird das Encoding der Client-Anwendung aus der Session verwendet. - Und das kann ja Grundsätzlich erst einmal nicht die Ursache sein.

Dennoch hier die Encodings:

  • Standardencoding Datenbank:
    Charset: WE8ISO8859P15

  • Encoding aus der Client-Session (Oracle 12 Client):
    Charset: WE8MSWIN1252

  • Encoding aus der Client-Session (Oracle 11 Client):
    Charset: WE8MSWIN1252

Wie man sieht gibt es bis auf den Encoding-Unterschied zum Server, der eigentlich keine Rolle spielen sollte kein Problem. Daher wundert mich dass die beiden Ausgabeparameter vom Typ "char" unterschiedliche Längen haben auf den jeweiligen Clients.

Vorstellen kann man sich das Verhalten wie folgt:


Anfrage-Länge     | Client 11                    | Client 12 
----------------------------------------------------------------------------------------
8 Zeichen            | "12345678"                 | "1234"
16 Zeichen          | "12345678        "         | "12345678"

Dieses oben dargestelle Phänomen wundert mich eben. Da ich keine klare Ursache finden kann.

18.04.2018 - 16:47 Uhr

Wäre aber sehr merkwürdig. - Bei beiden Rechnern (einmal mit OracleClient 11 und einmal mit OracleClient 12) werden exakt die gleichen Session-Variablen zur Sprache, Bytelänge und zum Charset ausgegeben.

18.04.2018 - 16:07 Uhr

verwendetes Datenbanksystem: Oracle 11.2.0.1.0

Hallo,

in einer bei uns im Haus entwickelten Anwendung wird eine Prozedur aufgerufen, die seit Jahren mit dem OracleClient 11 korrekte Daten lieferte. Nach Update auf OracleClient 12 passen die Daten aber nicht mehr.

Die Prozedur liefert 2 Ausgabeparameter vom Typ "CHAR" zurück. Bisher wurde als Länge für die Parameter 8 bzw. 1 angegeben. - Bei Kollegen mit OracleClient 11, kommen dann auch 8 bzw. 1 Zeichen zurück.

Beim Kunden, sowie auf meinem Entwicklungsrechner mit OracleClient 12 scheint sich die Länge allerdings auf das doppelte geändert zu haben. Das heißt nur mit Länge 16 bekomme ich auch 8 Zeichen.

Kennt jemand das Problem und weiß, warum das so ist? Ich kann bei Oracle leider keine vernünftige Begründung finden.

12.04.2018 - 16:30 Uhr

Hallo,

noch ein schönes Beispiel für Interfaces sind die ADO.NET Zugriffsklassen für Datenquellen. Meine Datenbank-Client-Klasse (DatenbankClient ADO.NET - Providerunabhängig) greift auf eine Datenbank zu. Welche das ist, entscheidet sich auf Basis der im Konstruktor übergebenen Informationen.

Der Datenbank-Client-Klasse ist es auch völlig egal, welche Datenbank-Klasse dahinter liegt, da die Methoden über die Schnittstelle definiert sind.

12.04.2018 - 16:03 Uhr

Hallo,

ich habe unter ideone mal ein Praxisfernes Beispiel erstellt.


    using System;
     
    public interface IMessageOutput
    {
    	void Out(string message);
    }
     
    public class ConsoleMessageOutput : IMessageOutput
    {
    	public void Out(string message)
    	{
    		Console.WriteLine(message);
    	}
    }
     
    public class ExtendedConsoleOutput : IMessageOutput
    {
    	public void Out(string message)
    	{
    		Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + " " + message);
    	}
    }
     
    public class Worker
    {
    	private IMessageOutput _output;
    	public Worker(IMessageOutput output)
    	{
    		_output = output;
    	}
     
    	public void DoWork()
    	{
    		for(int i = 0; i < 10; i++)
    		{
    			_output.Out("Counter: " + i);
    		}
    	}
    }
     
    public class Test
    {
    	public static void Main()
    	{
    		Worker worker = new Worker(new ConsoleMessageOutput());
    		worker.DoWork();
     
    		Worker worker2 = new Worker(new ExtendedConsoleOutput());
    		worker2.DoWork();
    		// your code goes here
    	}
    }

Ich habe hier 2 Worker die einfach nur von 0 bis 9 Zählen und eine Ausgabe machen. - Wohin die Ausgabe gemacht wird, ist der Worker-Klasse egal. - Diese bekommt ein Objekt vom Typ "IMessageOutput" und erwartet die Methode "Out". Die Worker-Klasse weiß auch nicht, ob der übergebene "IMessageOutput" vom Typ "ConsoleMessageOutput" oder "ExtendedConsoleOuput" ist. - Ist diesem auch egal.

Zum Thema Entkopplung. Das sieht man hier sehr schön. Der Worker soll eine Ausgabe machen. - Wie ist ihm egal. Das wird ihm von außen durch das Objekt des Typs "IMessageOutput" mitgeteilt.

Musst du nun Ausgaben woanders hin machen, musst du nicht an X-Stellen ConsoleMessageOutput durch FileMessageOutput ersetzen, sondern übergibst einfach die entsprechende Instanz an den Worker.

Aber eine Schnittstelle nur zu nutzen, weil ich beliebig viele implementieren kann...? 😕

Das habe ich nie gesagt. - Es ging erstmal nur um eine kurze Erklärung dazu. Für Interfaces gilt eigentlich der bekannte Leitspruch: "So viel wie möglich, so wenig wie nötig.". Wenn du von Beginn an weißt, dass immer eine feste Implementierung von Klasse X verwendet wird, brauchst du keine Schnittstelle.

12.04.2018 - 15:33 Uhr

Ich glaube du missverstehst den TE ein wenig. Er hatte wohl eher Fragen wofür der Typ "interface" gut sein soll.

Zum einen steht das wofür der Typ ist bereits im Eingangspost, zum anderen geht es ihm eher um die Verwendung wofür er speziell diese nutzen sollte.

Aber nun zu einer kurzen Erklärung bzgl. Interfaces:

Man kann sich ein Interface wie eine Abstrakte Klasse vorstellen. Also Vorgaben welche öffentlichen Member eine Klasse bereitstellen muss um in den Programmteilen verwendet werden zu können. Im Gegensatz zu abstrakten Klassen, kann eine Klasse beliebig viele Interfaces implementieren. Bestes Beispiel ist da aus meiner Sicht die generische List<T>-Klasse aus dem Framework.

Interfaces helfen auch dabei, Programmteile zu entkoppeln und so flexibler in der Implementierung und später bei Änderungen zu sein.

@App:
Du verwendest unbewusst mit Sicherheit sogar Sprachfeatures die ohne Interfaces nicht mal möglich wären.

foreach-Schleifen z.B. setzen auf das Interface IEnumerable um alle Einträge zu durchlaufen. Nur dadurch ist es möglich verschiedenste Auflistungen (Array, List<T>...) in diesen zu verwenden.

@panicJonny:
Dir ist ein Fehler in deinem Beispiel unterlaufen. Deine Voltage-Powersupply ist keine Manson-Powersupply. Du programmierst also die ganze Powersupply ohne Grund um oder verwendest sinnlos Interfaces, wenn du dann doch nur deine Manson hast die du umbastelst.

Korrekt wäre hier:


internal class MansonPowerSupply : IPowerSupply{
     public void setVoltage(double value) => // was auch zu tun ist;
     public void setMaxCurrent(double value) => // hier ist was anderes zu tun;
     public double getCurrent()  => return current;
}

internal class VoltcraftPowerSupply: IPowerSupply{
     public void setVoltage(double value) => // Voltcraft zeugs;
     public void setMaxCurrent(double value) => // hier anderes Voltcraft zeugs;
     public double getCurrent()  => return current;
}

10.04.2018 - 13:39 Uhr

Aufbauend auf alles bisher gesagte, ist eventuell folgendes ein Ansatz für dich:
*Videos auf Filesystem (natürlich auf dem Intranet-Server) *Datenbank nur für Indizierung, Videobeschreibung und Details

Wird ein neues Video abgelegt ergeben sich also die 2 Schritte: Speichern des Videos und Speichern der Indizierungsinformationen.

Bei Aufruf aus der Clientanwendung kann der Benutzer ein Video auswählen (auf Basis der Indizierungsinformationen) und zum Abspielen wird das Video vom Filesystem geladen.

29.03.2018 - 15:30 Uhr

Naja, damit wir dir aber hilfreiche Anstöße geben können, wäre dennoch wichtig wie du die vorherigen Aufgaben gelöst hast und wie das Ergebnis aussieht.

29.03.2018 - 15:17 Uhr

Wie sieht die List-Klasse aus? Ist diese ebenfalls generisch oder die Node-Klasse? Davon hängt meines Erachtens nach ab, wie die konkrete Implementierung aussehen kann.

28.03.2018 - 13:21 Uhr

Dann wäre mein Vorschlag mal alle unbehandelten Ausnahmen zu fangen und in eine Log-Datei zu schreiben, um erst einmal zu ermitteln wo die Anwendung denn überhaupt Crasht.

Statische Lock-Objekte halte ich gerade im Web für Grenzwertig. Da gibt es mit Sicherheit bessere herangehensweisen.

Haben denn verschiedene Clients die gleiche Controller-Instanz? Ansonsten ist doch hier eine Thread-Synchronisierung überhaupt nicht zielführend da die Clients sowieso unter verschiedenen Kontexten laufen.

23.03.2018 - 14:45 Uhr

Hallo,

ich habe mal etwas gebastelt. Eventuell kannst du darauf aufbauen. Für dein erstes Beispiel funktioniert der Regex.


\s*(?<result>\w+).*\\n\s+(?<first>\w+).+\*\s+(?<second>\w+).+/\s*(?<third>[0-9]*)

Bis auf die Kommentare sollte das eigentlich fast für alle Varianten greifen.

13.03.2018 - 11:00 Uhr

Hallo,

die korrekte herangehensweise wäre aus dem Thread heraus ein Event auszulösen, auf das du reagierst.

Um deinen Code jetzt aber nicht all zu weit außeinander zu reißen wäre mein Vorschlag, dass du aus der Methode "DirectoryCopy" deine Methode "Msgb_Backup()" aufrufst.

In dieser musst du allerdings auf den Threadwechsel mittels Invoke achten.

23.02.2018 - 08:21 Uhr

Naja, wenn du aufhörst den Timer static zu verwenden, sollte das klappen. Dein Problem ist, dass der Timer bei "myTimer.Tick += play;" bereits existiert und ein Event gebunden hat. - Beim zweiten Aufruf gibt es eben ein zweiten EventHandler usw.

14.02.2018 - 16:08 Uhr

Hallo,

den Ansatz hatte ich bereits probiert aber nicht als praktikabel abgetan. - Gründe weiß ich gar nicht mehr. Irgend etwas hatte mich daran gestört.

Den zweiten Link sehe ich mir mal an. Wir nutzen die Anwendung aber auch auf Systemen < Vista. - Mal sehen ob sich daraus eine brauchbare Lösung erstellen lässt.

14.02.2018 - 15:49 Uhr

Naja, speziell bei größeren Logs mit mehr als 200K Einträgen fällt das schon ins Gewicht.

Wenn man Beispielsweise statt des "Application"-Logs das "Security"-Log nimmt startet die Beispielanwendung rasend schnell. - Beim Filtern kommt es dann aber zu ewigen Ladezeiten.

14.02.2018 - 13:47 Uhr

Ich habe zwar nach all dieser Zeit nicht die Hoffnung, dass jemand nun eine Idee hat, aber eventuell täusche ich mich ja auch.

Hat denn noch keiner Ereignisprotokolle in eigene Anwendungen geladen und das extreme zeitliche Problem gehabt? Ich meine, das Laden der Einträge ist ja noch verflucht schnell für die teilweise großen Datenmengen. - Aber wenn man dann für den Meldungsinhalt z.T. mehrere Sekunden warten muss wenn man diesen auslesen will ist das schon grenzwertig.

Ich habe bereits mehrere Ansätze versucht um das ganze zu beschleunigen. Darunter:*Bei Lesen bereits ein FormatDescription aufrufen => Lesen wird extrem langsam *Nach Laden über Multithreaded Meschanismus FormatDescription für alle Einträge aufrufen => Extrem langsam, Einträge werden auch trotz Multithreaded Meschanismus seriell gelesen (FormatDescription blockiert intern, Instanzübergreifend)

29.01.2018 - 11:48 Uhr

Hallo Munro,

Abt hat dir bereits einen Link zur Verfügung gestellt, der für dich hilfreich sein sollte. Dein Problem ist, dass die Textbox in die du schreibst nicht aus dem Backgroundworker heraus beschrieben werden darf.

24.01.2018 - 09:35 Uhr

Hallo,

ich hatte gestern mal ein wenig rumprobiert (nachstellen und mögliche Lösung ermitteln). Daher kann ich einen Screenshot anhängen. Eine Lösung habe ich allerdings nicht gefunden.

@ChrisProg:
Ist es für euch Überlebensnotwendig, dass die MDI-Childs das Windows 10 Layout verwenden?

17.01.2018 - 16:31 Uhr

Wir haben uns nun temporär damit beholfen, dass wir eine Anzeige-Zeitspanne setzen.
Damit funktioniert es erst mal (nicht perfekt, da der ToolTip bei wechsel noch erhalten bleibt, aber nicht mehr ewig).

17.01.2018 - 14:43 Uhr

Hallo,

ich habe eine reihe von UserControls, die in einem TabControl dargestellt werden. Mittels der ToolTip-Klasse zeige ich auf dein einzelnen Controls in gewissen Fällen ToolTips an.

Wird nun der Tab gewechselt oder nur schnell genug verlassen, bleibt der Tooltip bestehen.

Ich habe bereits versucht bei Mouse-Leave der ListView der das ToolTip zugeordnet ist, ein Hide() auszuführen. - Funktioniert nicht.
Der nächste Ansatz war im Visible-Changed des UserControls Hide() zu setzen. - Auch das funktionierte nicht bzw. erst, wenn das UserControl durch Tabwechsel wieder sichtbar wurde.

Angezeigt wird das ToolTip im MouseMove der ListView:


        private void lvObservationValues_MouseMove(object sender, MouseEventArgs e)
        {
            if(tip == null)
            {
                tip = new ToolTip();
            }
            try
            {
                Point clientPoint = new Point(e.X, e.Y);
                ListViewItem item = this.lvObservationValues.GetItemAt(clientPoint.X, clientPoint.Y);

                if (item != null && !String.IsNullOrEmpty(item.ToolTipText))
                {
                    if (!tip.Active || lastTooltip != item.ToolTipText)
                    {
                        tip.Show(item.ToolTipText, this.lvObservationValues, clientPoint.X, clientPoint.Y);
                        lastTooltip = item.ToolTipText;
                    }
                }
                else
                {
                    tip.Hide(this);
                    lastTooltip = string.Empty;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

11.01.2018 - 16:26 Uhr

Regulär sollte das bei jeder Forms-Anwendung funktionieren.

Hast du eventuell irgendwelche festen Einstellungen bzgl. der Größe oder ähnlichem vorgenommen?

10.01.2018 - 14:37 Uhr

Hallo,

ich denke dass die hier beschriebenen Informationen eigentlich eine gute Basis liefern um ein brauchbares System zu modellieren.

10.01.2018 - 14:15 Uhr

Hallo ThomasE,

deine Lösung ist natürlich die sauberere. Für den aktuellen Anwendungsfall, nehme ich aber an dass diese EinzelElemente nur Bestandteil von "BasisKlasse" sind und damit eine feste Kopplung möglich ist.

Spätestens wenn fritziiiii die Elemente noch an anderer Stelle initialisiert die nichts mit "BasisKlasse" zu tun hat sollte er natürlich die saubere Umsetzung in Betracht ziehen und über Events den Status anfragen.

10.01.2018 - 11:53 Uhr

Habe ich das Prinzip jetzt komplett verstanden dann durch Kommandos deren Ausführung persistiert wird.

Wird nun ein Kommando ausgeführt, wird in Form einer Zeichenkette z.B. bei Änderung einer Property eines Objektes der alte und der neue Wert gespeichert. Meinetwegen in Textform: "Änderung Nachname von Muster nach Müller".

Je nach Komplexität des Systems kannst du im einfachsten Fall eine Tabelle verwenden die irgend eine Verbindung auf das eigentliche Objekt und die letzte Änderung besitzt.

Meinetwegen:
TargetType | TargetID | Command
Device | 1 | Changed device state from off to on
User | 435 | Changed users lastname from Muster to Müller

10.01.2018 - 11:11 Uhr

Möchte man den aktuellen Zustand eines Objekts haben, wird dieses anhand des Logs rekonstruiert. Für bessere Performance gibt es dann Snapshots, damit man nicht immer das ganze Log durchlaufen muss. Gelöscht wird nie irgendetwas.

Was ich aus der Beschreibung lese, geht es nicht um den aktuellen Zustand des Objektes, sondern der Nachverfolgbarkeit / Nachstellbarkeit, wie das Objekt in den aktuellen Zustand kam. - Das heißt, der aktuelle Zustand wird nach wie vor komplett gespeichert und zusätzlich quasi die Änderungen die durchgeführt wurden. Daraus schließe ich, das von mir beschriebener Ansatz (abzüglich der Löschung) eine einfache Implementierung des Prinzips ist.

EDIT: Die vollständige Implementierung würde natürlich nicht einfach in einer History-Tabelle münden. - Vollständig würde dann eher etwas gespeichert werden wie "Änderung Objekt X an folgenden Stellen".

10.01.2018 - 10:11 Uhr

Hat jetzt nichts mit EventSourcing zu tun, aber wir handhaben soetwas meist derart dass es eine "History"-Tabelle gibt, in die die vorhergehenden Einträge übernommen werden.

Soll also ein bestehender Eintrag in TabelleX per Update geändert werden, wird der bisherige Eintrag in die TabelleXHistory übertragen. Nach n-Tagen werden Einträge aus der History dann gelöscht.

Moment, wenn ich Event Sourcing korrekt verstanden habe, ist es ja quasi genau das...

10.01.2018 - 10:04 Uhr

Was Sir Rufo meinte war eher der Ansatz, dass deine Elemente eine Referenz auf den Parent haben.

In deinem Fall:


public class EinzelnesElement
{
      private BasisKlasse _parent;
    
      public EinzelnesElement(Basisklasse parent)
      {
          this._parent = parent;
      }

      public void StatusAbfragen()
      {
           // wie auch immer deine Statusabfrage aussieht
           this._parent.Status ??? 
      }
}

05.01.2018 - 15:36 Uhr

Wie sieht denn das Dokument aus, wenn das gespeicherte Dokument gedruckt wird?

04.01.2018 - 08:55 Uhr

Der Controller muss nichts zwischenspeichern. Der Controller darf doch gern direkt aufs Model greifen.

03.01.2018 - 16:48 Uhr

Ich würde auch sagen, dass die Umrechnung im View nichts zu suchen hat. Ich würde mich da im ersten Schritt an einem Aufbau wie folgendem Versuchen:

=> View (Anzeige, Converterwechsel etc)
=> Controller(Änderungen am Model, wenn Convert gewechselt wird bzw. ein Wert geändert wird)
=> Model (Wert 1; Einheit 1 [durch Converter bestimmt]; Wert 2 [umgerechneter Wert]; Einheit 2 [durch Converter bestimmt], Liste aller verfügbaren Converter, gewählter Converter)

Du kannst im Controller anschließend auf Property-Changed des Models horchen und bei Eingabe eines Wertes bzw. bei wechsel des Converters entsprechend reagieren.

20.12.2017 - 09:54 Uhr

Um hier eine Antwort geben zu können benötigen wir weitere Informationen über deine Anwendung. Sind noch andere Controls enthalten? Passt die Skalierung für die anderen Controls?

19.12.2017 - 13:22 Uhr

Aber das Load-Event des UserControls würde schon direkt bei der Instantiierung aufgerufen werden (nicht erst, wenn die TabPage selektiert wird).

Das widerspricht meinen Erfahrungen mit UserControls auf TabPages. - Das Load wird in allen Anwendungen, die ich derart aufgebaut habe immer erst nach Auswahl der Registerkarte ausgeführt.

19.12.2017 - 09:04 Uhr

Neben dem Ansatz mit dem SelectedIndexChanged bietet sich eventuell auch ein UserControl an?
UserControl unterstützt Load und wird exakt einmal aufgerufen. Dort kannst du dich dann auch an das Event hängen.

12.12.2017 - 16:45 Uhr

Der korrektere Ansatz wäre doch eher:


Bauwerk garage = new Garage();
Bauwerk wohnhaus = new Wohnhaus();

MachWas(garage, 44,12,4);
MachWas(wohnhaus, 20,10,50);

12.12.2017 - 16:42 Uhr

Dadurch, dass du alles Oder-Verknüpfst ist die Bedingung dann true, wenn auch nur eine der Teilbedingungen erfüllt wird.

Das heißt:
Eingabe != Empty und Eingabelänge != 2 und Eingabelänge != 6 und ist zahl

Deine Bedingung macht folgendes:
Führe die Schleife solange aus, wie keine leere Eingabe erfolgte oder die Eingabelänge nicht 2 oder 6 beträgt oder es keine Zahl ist.

Das heißt, wenn ich "Hallo" eingebe, ist die Bedingung wahr. Egal was die anderen Teilbedingungen sagen. Das größte Problem ist eher dein logisches Verständnis. du prüfst TryParse auf false. - Dann ist deine Bedingung wahr, wenn ein Text drin steht.