Laden...

Forenbeiträge von Pimsti Ingesamt 57 Beiträge

07.07.2010 - 11:14 Uhr

Vielen Dank für Eure Anregungen und Verbesserungsvorschläge.
Bin gerade dabei einiges einfließen zu lassen.

Eine Frage hätte ich jedoch noch an dieser Stelle:
Nachdem ich die Grundfunktionen einer Kioskfunktion inkl. Verwaltungs- & Kommunikationsklassen in ein Basisframework packe, kann ich das schön verwalten, wenn ich penibel (wie es JAck30lena vorgeschlagen hat) die Buildversionen inkrementiere und ggf. mit "use specific version" arbeite.
Wenn ich nun eine Kisokanwendung erstelle, lade ich die DLL mit dem Basisframework. Nun habe ich noch eine 2.Library in dem die verschiedensten Screens archiviert sind (z.B. UserverwaltungsScreen, ParameterScreen,...)
Gibt es eine Möglichkeit, dass ich die einzelne Screens (sind bei mir von UserControl abgeleitet) eine Versionsnummer vergebe?
Denn zurzeit sind ja alle Screens in einer Bibliothek und somit wird die Versionsnummer der daraus resultierende DLL immer weiter inkrementiert, egal bei welchen Screen ich Erweiterungen vornehme.
Ich will aber auch nicht jeden Screen in eine eigene DLL packen.

Was gibts hierzu für Vorschläge von Eurer Seite?

02.07.2010 - 08:34 Uhr

Hi!

Ich suche nun schon Stunden nach Artikeln & Ressourcen zum Thema Versionsverwaltung von Code-Files.
Irgendwie gebe ich immer die falschen Schlüsselwörter ein da ich nicht die Beiträge bekomme die ich suche.

Ich habe in den letzten Monaten & Jahren viele kleine Features programmiert und darauf geachtet, das diese so strukturiert wie möglich aufgebaut sind, sodass ein hohes Maß an Wiederverwendbarkeit gegeben ist.

Die verschiedenen Features sind in verschiedenste Projekt integriert und entwickelt worden.

Nun möchte ich diese "herauslösen" und in ein eigenes Framework packen. Dies ist nicht das Problem ... da bin ich auch auf einem guten weg.

In der Vergangenheit war es meist so, das ein bestimmtes Feature in einem Projekt auscodiert, getestet und eingesetzt wurde.
Hatte ich das Feature bei einem anderen Projekt verwenden können, habe ich die Klassen kopiert und im neuen Projekt dann meist weiterentwickelt.

Nun möchte ich in Zukunft die Weiterentwicklung im eigenen Framework machen. Dies muss jetzt aber dokumentiert werden.

Ich habe irgenwie noch keinen Plan wie ich das am besten anstellen soll.
Ich dachte mir ich füge ganz am Anfang des Code-Files einen Text-Header ein in dem ich so ein Update-Log habe und immer das aktuelle Datum wann von wem was geändert wurde eintrage.
Nur ist dies ziemlich mühsam dies zu dokumentieren.

Was mir am wenigsten klar ist wie ich das handeln soll will ich an einem kleinen Beispiel erläutern:

Bisher habe ich immer wie bereits erwähnt ein Feature im Zuge eines Projektes entwickelt und getestet und dort auch eingesetzt.
Habe ich dieses bei einem nächsten Projekt brauchen können habe ich die Files kopiert und dann fast immer weiterentwickelt und im neuen Projekt eingesetzt.
Nun habe ich ja 2 Versionen von einem Feature. Das alte im 1.Projekt und das neue im 2.Projekt.
Das war bisher nicht so ein Problem, da ich halbwegs den Überblick hatte und immer das hergnommen habe das für mich für die jeweilige Aufgabenstellung gepasst hat.

Wenn ich nun aber den Schritt gehen will, das ein Feature in eine Library eines Frameworks kommt, habe ich ja da immer nur die aktuelle Version. Auf die alten Versionen kann ich ja nicht mehr zugreifen, da diese überschrieben werden.

Wie geht ihr da so vor?
Verlaufe ich mich da in was?

Irgendwie sehe ich den Wald vor lauter Bäumen nicht mehr.

Zur Info: Habe mir gerade 2 Bücher über die allgemeine Softwareentwicklung reingezogen, nur da wird nirgends auf dieses Thema wirklich eingegangen

Ich hoffe ihr könnt mir Impulse dafür geben.

05.06.2010 - 07:25 Uhr

Vielleicht kann mir jemand bei folgendem Beispiel auf die Sprünge helfen.
Ich will beim Start der Applikation ein Form aufgehen lassen, bei dem ganz Simpel "Loading" da steht und "." rüberwandern bis eine gewisse Zeit abgelaufen ist. Die Zeit wird groß genug gewählt, sodass alle "Applikations-Bootvorgänge" abgeschlossen sind und danach sofort die GUI-Funktionsfähig verwendet werden kann. Hier ein Snippet dazu:


        private void startBox(object o)
        {          
            new SmaStartBox(this.Size, 450, 12000);
        }
        
        private void Form1_Load(object sender, EventArgs e)
        {   
            startBox(new Object());
            

            ... STARTSTUFF .... // dauert ca. 12 Sekunden
        }

Bei dieser Lösung wird Form1 (mein Main-Form) gestartet und im Load-Event zuerst die Startbox (ist ein Form das neu instanziert und angezeigt wird) angezeigt und dann in den darauffolgenden 12-Sekunden der BootUpStuff abgearbeitet.

Hier nun die "parallele" Variante


        private void startBox(object o)
        {          
            new SmaStartBox(this.Size, 450, 12000);
        }
        
        private void Form1_Load(object sender, EventArgs e)
        {   
            ThreadPool.QueueUserWorkItem(new WaitCallback(startBox), null);
            

            ... STARTSTUFF .... // dauert ca. 12 Sekunden
        }

Hier wird nun aber beim ausführen von "new SmaStartBox(this.Size, 450, 12000);" eine NotSupportedException geworfen mit der Meldung "Control.Invoke must be used to interact with controls created on a separate thread."

Noch zur Info: Dies ganze wird im VS2008 auf einem CE-Gerät (WinCe5.0) unter CF2.0 emuliert.

Kann mir hier jemand Licht ins Dunkle bringen?

02.06.2010 - 15:27 Uhr

Naja mit irgendwas muss ich ja anfangen ... und es ist ja jetzt kein abstraktes Problem das ich lösen will
...
Ich habe schon viel über Threads nun gelesen ... die Versuche haben auch alle geklappt.
Nun habe ich wie weiter oben schon beschrieben in einem GUI-Thread eine Methode über ThreadPool.QueueUserWorkItem(new WaitCallback(xxx)) gestartet.
Diese muss ja jetzt asynchron, also parallel zur Oberfläche laufen.
Warum kommt es trotzdem auf meiner WinCE Plattform bei meiner GUI zu "aussetzer" bei der ich sie nicht mehr bedienen kann? Sollte doch absolut parallel laufen? Mir würde jetzt auch nichts von der mir gelesenen Literatur einfallen, das dieses Phäneomen erklären würde ....

02.06.2010 - 12:59 Uhr

@herbivore: Tja leider bin ich ein Newby in Sachen Threads und experementiere gerade ein bisschen damit. Ich habe jetzt schon viel Literatur dazu gelesen jedoch ist mir der Begriff "Racing Condition" noch nicht unter gekommen ...

@svenson: Auch in dieser beziehung bin ich wohl zu grün hinter den Ohren ... wie würdest Du solche logs aufbauen ... überall einfach Punkte im Code setzten und diese in ein File schreiben? Oder mehrere Files mit Zeitstempel ...

Bin für jede Anregung dankbar!

02.06.2010 - 11:23 Uhr

So hier mal auszugsweise der Code zu meinem Problem:


    public partial class Screen_Work : SMABaseScreen
    {

        ....

        public Screen_Work()
        {
            ...
            smsModule = new SMAGsmSms("COM3", "4863");
            ...
        }


	public void initComADS(ComADS comADS)
        {
            ...
            ThreadPool.QueueUserWorkItem(new WaitCallback(initGsmModul));
        }

        private void initGsmModul(object o)
        {
            ...
            switch (smsModule.initConnection())
            {
                ...
            }
        }

    }


    public class SMAGsmSms
    {
        ...


        void comAds_variableValueInPLCChanged(object sender, EventArgs e)
        {
            ...

        }


        private void initTimeout(object o)
        {
            T_InitTimeout.Dispose();
            initIsRunning = false;
            OnTimeoutInit();
        }


        public AckState initConnection()
        {
            initIsRunning = true;
            errorState = AckState.NO_ERROR;
            if (state == State.WAITING_FOR_INIT || state != State.READY_FOR_INIT)
            {
                T_InitTimeout = new System.Threading.Timer(tcb_initTimeout, null, 20000, 8000);
            }
            state = State.WAITING_FOR_INIT;
            //wait for ReadyForInit-Signal
            while (state != State.READY_FOR_INIT) 
            {
                if(!InitIsRunning)
                    return AckState.HARDWARE_NOT_READY;
            }
            T_InitTimeout.Dispose();
            ser.BufferContent = "";

    }

Die Screen_Work-Klasse wird als erste instanziert (ist von UserControl abgeleitet).
Im Konstruktor dieser Klasse wird die SMAGsmSms instanziert.
Nach dem Instanzieren wird sofort die initComAds-Methode von Screen_Work aufgerufen.
Dort wird am Ende in ein asynchroner Thread mittels Threadpool aufgerufen in dem die MEthode initGsmModul aus Screen_Work läuft.

Hier der erste Unterschied zwischen den 2 Laufvarianten.
Unter WinXP&.NET-Framework3.5 läuft es wie erwartet: Die INitialisierung läuft parallel und die Oberfläche bleibt bedienbar.
Unter WinCE&Compact.NET-Framework2.0 kommt es immer wieder zum "Hängenbleiben" ... öfters ist es für mehrere Sekunden bedienbar ... öfters hängt es aber auch die ganze Zeit bis der Thread des Threadpools abgearbeitet wurde.

Weiter will ich noch gar nicht erklären da es evtl. mit einer Antwort schon mitgelöst werden kann.

02.06.2010 - 10:09 Uhr

Ich habe ein Applikation unter WinCE im CompactFramework2.0 entwickelt.
Hier hatte ich Probleme bei einer Thread-Anwendung.
Nun habe ich den selben Code auf einem XP-Rechner ausgeführt (im .NET-Framework 3.5) und da funktionierts?

Gibt es grundsätzlich unterschiede vom Thread-Verhalten unter WinCE und WinXP?

25.05.2010 - 13:43 Uhr

Ich habe ein Applikation mit einem Windows.Form gestartet.
Nun möchte nach dem Klick auf einen Button, dass ein neues Form aufgeht und dieses solange im Vordergrund bleibt, bis ich darauf die Dateneingabe vollzogen haben. Wenn ich dieses Form wieder schließe sollen die Daten durch return übergeben werden (so ähnlich wie es Messagebox.show(...) macht).

Funktion:


        private void button1_Click(object sender, EventArgs e)
        {
            string erg = TestInputApp.show();
        }

Das heißt die show-Methode muss static sein.
Mein erster Ansatz war es, das TestInputApp von Form abhängt ... das habe ich einfach nicht hinbekommen.
Der Ansatz an dem ich jetzt arbeite (und mir die Zähne ausbeiße) ist, dass in der static-Methode show der static-Klasse TestInputApp eine neue Instanz von einem Windows.From erstelle.
Hier die Sachen die ich nicht hinbekomme:
1.) die neue Windows.Form Ínstanz bleibt nicht im Vordergrund
2.) Die TestInputApp.show-Methode solange anhalten bis die neu Form-Instanz über ein Event signalisiert, das die Daten in TestInputApp bereitgestellt wurden und diese nun retourniert werden können.

Kann mir hier jemand ein paar hilfreiche Tipps geben?

25.05.2010 - 13:33 Uhr

werde es gleich mal probieren ... vielen Dank für die Infos!!

25.05.2010 - 12:10 Uhr

Ich habe in der t_tick Methode folgende Anweisungen:

B_SMA_FileWrite.setBlue();
Data.resaveDB();
B_SMA_FileWrite.setGreen();

Funktion:
1.Buttonhintergrund wird auf blau gesetzt
2.File wird kopiert mit File.Copy(Data.DbHostNameWork, Data.DbHostNameStore);
3.Buttonhintergrund wird auf grün gesetzt.

Wenn ich den Code debugge und die 1.Zeile ausgeführt habe, wechselt der Button nicht auf Blau.
Beim Ausführen von. Zeile 2 (dies dauert ca. 3-4 Sekunden) passiert auch noch nichts.
Wenn ich Zeile 3 ausführe passiert auch nichts.
ERst wenn ich aus der Methode t_tick springe wechsel der Button auf grün.

Warum?

25.05.2010 - 11:51 Uhr

Ich habe ein Windows.Form in dem ich zyklisch einen System.Windows.Forms.Timer (Interval=5000ms) laufen lasse.
Ich melde mich an das Tick-Event mit dem Delegate t_tick an.
Frage 1: Der Timer t wird in einem neu erstellten Tread erzeugt - korrekt?
Frage 2: Wird der Code unter t_tick in der Laufzeit des Timer-Threads durchgelaufen?
Frage 3: Bleibt die GUI während der Abarbeitung des Codes unter t_tick "bedienbar", da ja der GUI Thread parallel laufen müsste?

Fragen folgen noch, nur will ich auf diese Antworten warten, damit sich evtl. manche Fragen schon beantworten

Vielen Dank für Eure Erleuchtung ;O)

20.04.2010 - 09:33 Uhr

Ich habe ein Datagrid in dem Zeilen je nach inhalt automatisch selektiert werden.
Immer wenn ich auf eine Zelle Klicke rufe ich eine Methode auf, in der die Selektierung der "aktiven" Zeilen (abhängig von dem Zeileninhalt) aktulisiert wird.
Dabei setzte ich nicht nur die Selektierung der aktiven Zeilen mit DG_Meldungen.Select(x) sondern auch DG_Meldungen.CurrentCell = new DataGridCell(j, 0); auf die erste Zeile die selektiert ist.
Somit kann ich auch auf Zeilen klicken die nicht selektiert sind ohne, dass die angeklickte Zelle selektiert wird.
Nun habe ich aber folgendes Problem:
Wenn keine Zeile selektiert werden soll (da die Inhalte dies so verlangen), dann soll auch keine Zelle selektiert werden.
Wie schaffe ich es:
1.) Beim Laden des Controls, dass die Zelle 0,0 nicht selektiert wird
2.) bei einem Klick auf eine Zelle diese nicht aktiviert wird

12.04.2010 - 15:03 Uhr

Das einige Funktionen nicht implementiert sind und andere Compact-spezifisch nur hier funktionieren ist mir klar - die Frage ist ob mein geschildertes Problem ein Anwendungsfehler meinerseits ist oder diese Funktion für das Compact-Framwork bzw. für SmartDevice-Projekte allgemein nicht funktioniert.

12.04.2010 - 14:11 Uhr

Ich habe mir auf eine "Benutzersteuerelement" hinzugefügt auf dem ein Button liegt der verschiedene Funktionalitäten (Farbblinken,...) hat.
Dieses habe ich bislang immer bei XP-Applikationen verwendet.

Verwendet habe ich ihn immer so, dass ich ihn aus der Toolbox auf mein Form gezogen habe (das heißt er hat mir das "Benutzersteuerelement" in der Toolbox angezeit)

Nun brauche ich etwas ähnliches in CE.
Hier ist mir beim ERstellen auf aufgefallen, dass ich dieses Benutzersteuerelement, welches ich neu erstellt habe nicht reinziehen kann, da es grau hinterlegt ist.
Hängt das zusammen, weil ich für ein SmartDevice (WinCE) entwickle?
Gibt es die Funktion hier nicht?

11.04.2010 - 12:08 Uhr

Ja ich entwickle nur auf 32 bit. Das passt dann.

Ich dachte nur wenn ich den SQL Compact 3.5 auf das CE-Gerät installiere, dann sind die Pfade zu den DLLs gleich gesetzt.
Muss ich halt di DLLs ins App-Verezeichnis mitkopieren. Ist nicht tragisch aber eben nicht so praktisch für faule Programmiere 😉

11.04.2010 - 12:05 Uhr

As simple as that - Danke für die Hilfe 8)

10.04.2010 - 07:26 Uhr

Ich habe auf einer XP-Plattform eine Kioskanwendung erstellt.
Hierfür habe ich im MainForm folgende Codezeilen im Konstruktor ausgeführt:


this.WindowState = FormWindowState.Maximized;
this.ControlBox = false;
this.Text = "";

Dadurch habe ic hdie oberste Zeile ganz ausblenen können und die gesamte Form erstreckte sich über den ganzen Bildschirm.

Dies wollte ich nun auch für eine CE-Plattform haben.
Wenn ich hier die oben genannten 3 Code-Zeilen im Konstruktor des MainForms aufrufe, ist zwar oben rechts die ControlBox verschwunden sowie der Header-Text in der obersten Leiste und die Form erstreckt sich über den ganzen Bildschirm, jedoch verschwindet die oberste Leiste nicht.
Jetzt habe ich immer einen blauen Balken ganz oben.

Wie bekomme ich den weg?

10.04.2010 - 07:18 Uhr

verwendetes Datenbanksystem: SQL Server Compact 3.5
...
Ich entwickle eine CE-Applikation im Visual Studi 2008 auf einem XP Rechner.
Zum Testen der Software emuliere ich die Applikation am Zielsystem.
Auf dem Zielsystem habe ich den SQL Server Compact 3.5 installiert.
Wenn ich die App emuliere funktioniert alles so wie es sein soll.

Wenn ich jedoch die Applikation am XP Rechner aus dem Verzeichnis .\bin\Debug per Hand auf das Zielsystem in irgend einen Ordner kopiere (alle Dateien die in diesem Verzeichnis sind) und die Applikation dann starten will, fehlen ihm die Dateien:
o 'sqlcese35.dll'
o 'sqlceqp35.dll'
o 'sqlceme35.dll'

All diese Dateien habe ich unter dem Install-Verzeichnisses des CE-Zielsystems gefunden (\Hard Disk\Programme\Microsoft SQL Compact Edition\v3.5) gefunden.
Wenn ich diese per Hand in das Verzeichniss der App kopiere, funktioniert alles.

Wieso erkennt er die nicht schon automatisch?
Müssten nicht durch den Install-Prozess hier Systempfade gesetzt sein um diese zu finden?
Wo kann ich dies nachträglich selbst eintragen?

03.04.2010 - 14:27 Uhr

Ich habe vor eine GUI-App mit Datenbankanbindung zu programmieren, die auf Win XP & Win CE laufen soll. Dabei will ich schon viele vorhandene Oberflächen die derzeit mit dem .NET Framework kompiliert wurden verwenden.

Muss ich damit rechnen, dass die ganzen Oberflächen die ich bis jetzt habe in CE neu machen muss?

Wie geht ihr da vor wenn ihr Software für beide Plattformen entwickelt. Trennt ihr strickt Funktion und Oberfläche ... wie geht ihr da vor ... bitte gebt mir ein paar Tips auf was ich auf jeden Fall achten soll

Danke im Voraus für Eure Erfahrungen!

03.04.2010 - 11:45 Uhr

@herbivore:
zu 1.) habe ich probiert ... funktioniert leider nicht.

zu 2.) werde ich gleich mal ne umfassende Recherche anwerfen ... man muss eben nur die richtigen Begriffe kennen 8)

@Neals:
Wie soll ich die Shortcuts abfangen?
Vielleicht nochmals etwas mehr Infos:

  • es wird eine Instanz eines Forms erzeugt das oben genannte Eigenschaft hat, sodass nur noch das Leere-Panel ohne "Drumherum" sichbar ist.
    Die einzelnen Screens habe ich auf UserControls gemacht die übereinander gelegt werden und der aktuelle Bildschirm wird mit der Methode BringToFront() angezeigt. Somit ist immer ein UserControl im Vordergrund.
    Jetzt habe ich schon alle Varianten probiert, dass ich auf Tastendrücke Events abfange (sowohl in den UserControls sowie im parentForm) jedoch ohne Erfolg?!?
    Wenn ich das könnte könnte ich ja die Tastenkombinationen ohne Funktion überschreiben oder?
03.04.2010 - 05:00 Uhr

Hier meine Aufgabenstellung:
Es soll eine Applikation erstellt werden, welche nach dem Start immer im Vordergrundläuft - der User soll wenn möglich nicht die Möglichkeit haben auf andere Applikationen oder Windows-Tasks (wie z.B. Startmenü wechseln) zu können.
Mit folgenden Codezeilen im MainForm wurde dies mal profesorisch hingebracht:


            this.WindowState = FormWindowState.Maximized;
            this.ControlBox = false;
            this.Text = "";
            this.TopMost = true;

Hier die derzeitigen Krücken die nicht erwünscht sind:
1.) Wenn Instanzen von Dialogen aufgerufen werden, sind diese dadurch im Hintergrund. Daher wurde vor dem aufrufen TopMost auf false gesetzt und danach wieder auf true. Damit kann aber der User während der Laufzeit des Dialogs wieder auf andere Applikationen im Hintergrund wechseln
2.) kann mit ALT+TAB oder der WINDOWS-Taste noch der Taskwechsel-Screen bzw. das Startmenü geöffnet werden. Gibt es eine Möglichkeit dies zu verhindern?

Wenn einer von Euch mir bei diesen beiden Punkte weiterhelfen könnte wäre mir sehr geholfen!

02.04.2010 - 08:20 Uhr

Hab eine Antwort im Forum gefunden: Beitrag

02.04.2010 - 08:11 Uhr

zur Ergänzung: ich hätte probiert im Event 'CellValidated' die betreffende Zeile mit der Methode setModified() den RowState auf Modified zu setzen. Dabei ersetzt er aber in der Tabelle den geänderten Wert wieder auf den ursprünglich eingegebenen.

z.B.: vorher war '77' in der Zelle. Nach der eingabe '7788'. Wenn ich dann setModified() ausführe, wird der Zelleninhalt wieder auf '77' gesetzt und der RowState auf Modified gesetzt.

02.04.2010 - 08:00 Uhr

verwendetes Datenbanksystem: MS SQL Server Express 2005

Meine Aufgabenstellung: Wenn ich einen Wert in einer Zelle eines DataGridViews ändere und die Eingabe bestätige, checke ich durch das 'CellValidating' Event was drinnen war und danach durch das 'CellValidated' Event ob ggf. durch die aufgetretenen Änderungen dies in die Datenbank mittels da.Update(....) zurückgeschrieben wird und zusätzlich dazu nach aussen ein Event gefeuert wird (da ist eine Instanz des SqlDataAdapters).

Nun habe ich das Problem das zum Zeitpunkt des Eventaufrufes durch 'CellValidated' zwar der Wert in der Zelle bzw. in der Tabelle der geändert wurde schon drinnen steht, jedoch der RowState der betreffenden Zeile noch auf 'Unchanged' ist und somit ein ausführen der Update-Methode des DataAdapters keine Auswirkung hat.

Soll ich den RowState selbst änderen, oder ist dies eine unsaubere Programmierung, da ich evtl. dadurch andere Aspekte übersehe.
Wenn ja gibt es eine Möglichkeit im Event 'CellValidated' eine Methode aufzurufen, die den RowState früher aktualisiert?

15.01.2009 - 13:51 Uhr

Hier ein Codefragment das ich zu meinen Fragen benötige:


namespace Warum
{
    public partial class Form1 : Form
    {
        DatabaseCheck dbCheck;

        public Form1()
        {
            InitializeComponent();
            this.CreateHandle();
            initDBConnection();
            clock1.start();
            dbCheck = new DatabaseCheck("LOG\\Stempeluhr - Database.log", this.Name, Data.param);
            dbCheck.start();
            dbCheck.conLost += new EventHandler(this.connectionLost);
        }

       delegate void connectionListDel();
       private void connectionLost(object sender, EventArgs e)
       {
           try
           {
               DatabaseCheck.MyEventArgs ev = (DatabaseCheck.MyEventArgs)e;
               switch (ev.Connstatus)
               {
                   case DatabaseCheck.CONNECTION_LOST:
                       BeginInvoke(new connectionListDel(disableForm), new Object[] { });
                       break;

                   case DatabaseCheck.CONNECTION_OK:
                       BeginInvoke(new connectionListDel(enableForm), new Object[] { });
                       break;
               }
           }
           catch { }
       }

       private void enableForm()
       {
           this.Enabled = true;
           clock1.Pause = false;
           sc.Close();
           refreshTables();
       }
       private void disableForm()
       {
           this.Enabled = false;
           clock1.Pause = true;
           sc.Close();

       }

}

Mittels der Klasse DatabaseCheck soll zyklisch gecheckt werden ob eine Datenbankverbindung zu einem Server hergestellt ist bzw. werden kann.
Wenn ja läuft eine Uhr - wenn nicht dann bleibt diese Uhr stehen und wird "disabled".
In diesem Beispiel wird zyklisch von der Klasse DatabaseCheck ein Event geworfen in dem kontrolliert wird ob die Verbindung möglich ist oder nicht.
Abhängig davon wir eventuell die Methode disableForm() oder enableForm() aufgerufen. Dies wird über Delegates realisiert.

Kann ich nicht einfach diese Methoden direkt in der Event-Behandlungmethode aufrufen?

Wenn ja welche Gründe würden für die oben vorgestellte Variante mit Delegates sprechen?

25.11.2008 - 15:57 Uhr

Danke - jetzt hats funktioniert - hier nochmals meine Implementation:

String[] keyEntries = new String[parameterList.Keys.Count];
            parameterList.Keys.CopyTo(keyEntries, 0);
            SMAParameterValue[] valueEntries = new SMAParameterValue[parameterList.Values.Count];
            parameterList.Values.CopyTo(valueEntries, 0);

            for (int i = 0; i < keyCol.Count; i++)
                loadParameter(valueEntries[i].sectionName, keyEntries[i]);
25.11.2008 - 15:09 Uhr

Hätte es wie folgt probiert:

for (int i = 0; i < keyCol.Count; i++)
                loadParameter(parameterList[keyCol[i]], keyCol[i]);

Doch dies lässt der Compiler nicht zu.
Wie hast Du das mit der For-Schleife gemeint?

25.11.2008 - 14:07 Uhr

Habe folgendes Problem:
Habe eine Auflistung in einem generischen Dictionary wie folgt implementiert:

private Dictionary<string, SMAParameterValue> parameterList;

Dabei handelt es sich bei dem "Value"-Datentypen um einen von mir benutzerdefinierten Struct:

public SMAParameterValue(Object actualValue, Object defaultValue, String sectionName)
{
     this.actualValue = actualValue;
     this.defaultValue = defaultValue;
     this.sectionName = sectionName;
}

Nachdem ich dieses Dictionary erfolgreich mit Wertepaaren gefüllt habe, will ich zu einem späteren Zeitpunkt über alle Einträge iterieren und den Wert _actualValue _des Structs jedes Eintrages ändern.
Hierfür habe ich über die KeyCollection folgendermaßen iteriert:

            Dictionary<string, SMAParameterValue>.KeyCollection keyCol = parameterList.Keys;

            foreach (string keyName in keyCol)
                loadParameter(parameterList[keyName].sectionName, keyName);

In der Methode loadParameter wollte ich wie folgt den Wert für actualValue ändern:

SMAParameterValue paraTmp = new SMAParameterValue (parameterList[parameterName].actualValue, parameterList[parameterName].defaultValue, parameterList[parameterName].sectionName);
                    
paraTmp.actualValue = setting.Value;
parameterList[parameterName] = paraTmp;

Beim ersten Durchlauf der foreach-Schleife funktioniert dies, jedoch bei dem 2.Durchlauf kommt es zu dem Ausnahmefehler wie im Anhang im Screenshot dargestellt.

Anscheinend hat die foreach-Schleife ein Probelm damit wenn sich das der KeyCollection zu Grunde liegende Dictionary ändert bzw. die Values dessen.

Wie kann ich dem entgegnen?

08.11.2008 - 08:57 Uhr

Das DGV.EndEdit schiebt die editierten Daten an den Nichts ist so Beständig wie das provisorium, weshalb man soetwas immer gleich
richtig machen sollte.

Wie war - tja da liegt es wohl dann nur an der Disziplin dies dann wirklich zu machen ;O) Vielen Dank nochmals!

07.11.2008 - 11:40 Uhr

BindingSource verwenden und vor dem Speicher BindingSource.EndEdit aufrufen.

So funktionierts - Vielen Dank!
Aber ich verstehe anscheinend die Funktionsweise von dem BindingSource-Objekt nicht. Denn ich hätte zuvor ja probiert, dass ich die EndEdit-Methode des DGV verwende. Da funktionierts nicht. Wenn ich nun aber zwischen DGV und DataSet das BindingSource-Objekt dazwischen schalte und vom BindingSource-Objekt die EndEdit-Methode verwende, dann funktionierts?!?

Auch finde ich (modul)globale DataAdapter und CommandBuilder bedenklich.

Ich bin gerade am testen - danach wird's eh sauber ausprogrammiert ;O)

07.11.2008 - 11:23 Uhr

Das Konzept von ADO.Net geht doch dahin, daß ein Haufen Daten ausgelesen wird, :::

Man darf sich diese Anwendung nicht als eine herkömmliche DB-Anwendung vorstellen. Wäre natürlich sonst eine katastrophale Lösung - das ist mir schon klar.
hier geht es aber um eine Produktionmaschine auf der 2 PCs zugreifen und bei jeder kleinen Datenänderung beide PCs auf dem gleichen Stand sein sollen.
Also bitte nur auf meine Fragestellung fokusieren und dieses Performance-Detail bitte ausklammern

07.11.2008 - 11:20 Uhr

Du machst das im falschen EventHandler. Du müsstest eigentlich den
>
oder den
>
Event nutzen.

Habe ich beide schon probiert - Ergebnis ist leider das selbe.

Aber ich halte es für eine bad practice, jedemal in so einem EventHandler gleich zurück in die DB zu schreiben. Ich würde dem User lieber einen "Speichern"-Button anbieten.

Bei diesem Projekt bzw. bei diesem Feature muss dass so sein, da es sich hier um eine Maschinensteuerung handelt und der Parameter nach der Änderung sofort in der DB zur Verfügung stehen muss.

07.11.2008 - 11:08 Uhr

Ich habe ein DGV wie folgt mit einer Tablle aus meiner DB gefüllt:


            DS_Parameters = new DataSet();
            da = new SqlDataAdapter("SELECT * FROM Parameter WHERE SecLevel=" + secLevel + " ORDER BY Nr", sc);
            cb = new SqlCommandBuilder(da);
            sc.Open();
            da.Fill(DS_Parameters, "Parameter");
            sc.Close();
            DGV_ParaTable.DataSource = DS_Parameters.Tables["Parameter"];


Wenn ich nun Daten in einer Zelle ändere will ich nach dem Abschluß der Änderung dies in die Datenbank zurückschreiben.
Hierfür habe ich das CellEndEdit-Event des DGV abgefangen und folgenden Code implementiert:


        private void DGV_ParaTable_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            da.Update(DS_Parameters, "Parameter");
        }

Nun "hinkt" die Aktualisierung immer um einen Schritt nach - das bedeutet wenn ich einen Wert ändere tut sich noch gar nichts in der DB - wenn ich nun noch einen Wert ändere wird in der DB der zuvor geänderte Wert eingetragen, usw.

An was liegt das?

22.04.2008 - 10:30 Uhr

@nin: Ja habe es zur Laufzeit probiert ... funktioniert nicht ... habe auch den ganzen Code von mir und den, der autom. von der Entwurfsansicht ( VS2008 ) erzeugt wird. Nichts X(

22.04.2008 - 09:54 Uhr

Bei mir wird die Checkbox ausgegraut wenn ich Enabled auf false setzte und dann ist auch nichts mehr mit anklicken (.Checked kann noch zugewiesen werden).

Bei mir nicht 8o
Wie gibts denn das? 🤔

22.04.2008 - 09:33 Uhr

Nein ist es nicht ... kann man ganz leicht selber ausprobieren.
Habe Checkbox per Drag'n'Drop in der Entwurfsansicht auf ein Panel gezogen und unter den Eigenschaften Enable auf false gesetzt.
Danach beschreibe ich die Checkbox über die Eigenschaft Checked.
Jedoch kann ich per Mausklick denn Status beliebig negieren/invertieren.

22.04.2008 - 09:24 Uhr

Habe ein Checkbox und setzte den Status(Häkchen) anhand von eingelesenen Daten.
Diese Checkbox soll nur zur Anzeige von BOOL-Werten dienen. Ich möchte den Zugriff des Users darauf sperren. Ich habe dies schon mit verschiedenen Properties probiert (Enable, AutoCheck, ....).

Wie kann ich das gewünscht bewerkstelligen?

28.01.2008 - 08:51 Uhr

Habe einen SplitContainer in ein Usercontrol eingefügt mit Dock=Fill.
Ich will nun den Splitter fix 100 Pixel von rechts positionieren.
habe isSplitterfixed=true gesetzt und SplitterDistance=100
Er ist nun fix ... aber die Splitterposition ist eine relative, denn wenn ich die größe des UserControls ändere dann ändert sich auch der Abstand des Splitter vom Linken Rand weg?
Wie kann ich dies fixieren?

22.01.2008 - 11:21 Uhr

Ich habe in einem UserControl die Eigenschaft Text überschrieben.
Im set-Zweig wird die Übergabe auf Wertgrenzen durchgeführt.
Wenn ich das Projekt mit F6 im Visual-Studio 2005 kompiliere, dann wird anscheinend der Eigenschaft Text ein Wert zugewiesen.
Da der scheinbar übergebenen Wert ausserhalb den spezifizierten Grenzen liegt, werden div. Messageboxes ausgelöst.
Ich hätte schon das ganze mit !DesignMode abfangen wollen - nur funktioniert dies nicht.
Was kann ich machen?

18.01.2008 - 17:00 Uhr

Alles klar ... war mir noch nicht ganz klar wie das funktinioert ... aber ist ja nichts anderes als ein Delegate ... Werds dann gleich mal ausprobieren ... bin mir aber sicher das dies der Fehler war .. danke

18.01.2008 - 16:50 Uhr

Habe ein UserControl erstellt.
Hier ein Auszug mit dem zu bereitstellenden Event


public partial class MyMaskedTextBox : UserControl
    {
        public event EventHandler DataChanged;
        
        ....


        private void OnDataChanged()
        {
            EventArgs e = new EventArgs();
            DataChanged(this, e);
        }
   
        ....
}

Mit OnDataChanged() feuere ich das Event ... wenn dies der Fall ist bricht mir der Debugger mit folgender Meldung (--> siehe Anhang)

Was ist der Grund?

18.01.2008 - 11:52 Uhr

Mann bin ich ein .... 😜
Danke ... dass wars ...

18.01.2008 - 11:35 Uhr

Habe ein MaskTextBox Element mit Daten gefüllt.
Der String soll immer eine konstante länge von 10 Zeichen aufweisen.
Jetzt habe ich folgende Mask übergeben: '&&&&&&&&&&'

Nach der Eingabe sollen die Leerzeichen am Anfang und am Ende entfernt werden, und der String rechtsbündig auf 10 zeichen links mit Leerzeichen aufgefüllt werden.

Dazu habe ich das Validated-Ereigniss verwendet - wie folgt:


        private void MTB_ANr_Validated(object sender, EventArgs e)
        {
            String tmp = MTB_ANr.Text;
            tmp.Trim();
            tmp.PadLeft(10,' ');
            MTB_ANr.Text = tmp;
        }

Folgende Fehler:

1.) wenn ich mit dem Debbuger arbeite sehe ich nach ausführen von tmp.Trim(); die Leerzeichen links und rechts noch vorhanden sind?
2.) wenn der String aus 5 Zeichen besteht musst ja nach tmp.PadLeft(10,' '); der String aus 10 Zeichen bestehen wobei links 5 Leerzeichen und dann die bestehenden 5 Zeichen enthalten sein müssen ... funktioniert nicht?
3.) Wie kann ich, wenn ich vor dem String die Backspace-Taste einsetzte den String wieder linksbündig ausrichten?

Was habe ich an den Funktion falsch verstanden?

17.01.2008 - 10:31 Uhr

gibt es ein globales Property für die ganze Column-Collectin oder muss ich durch jedes durchiterieren?

17.01.2008 - 10:11 Uhr

Gibt es ein Property mit dem ich das Sortieren der Zeilen durch Klick auf den SpaltenHeader disablen kann?
Oder ist die einzige Möglichkeit das Event abzufangen und nichts zu tun?

17.01.2008 - 09:48 Uhr

habe es nun wie folgt gelöst:
Habe eine zusätzliche Spalte für Images hinzugefügt


            DataGridViewImageColumn dgvic = new DataGridViewImageColumn();
            dgvic.Name = "Status Symbol";
            dgvic.DefaultCellStyle.NullValue = null; 
            DGV_PanelTypen.Columns.Insert(0, dgvic);

Die Spalte mit den Status-Int-Werten lautet "Status.
In der CellFormatting-Event-Behandlungsmethode frage ich den Status ab und füge dementsprechend das richtige Image in die neue Spalte ein.
Die Status-Int-Spalte blende ich aus.



        private void DGV_PanelTypen_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (DGV_PanelTypen.Columns[e.ColumnIndex] == DGV_PanelTypen.Columns["Status Symbol"] )
            {
                switch(Convert.ToInt32(DGV_PanelTypen[DGV_PanelTypen.Columns["Status"].Index, e.RowIndex].Value.ToString()))
                {
                    case 0:
                        e.Value = applyImage;
                        break;
                    case 1:
                        e.Value = inProdListImage;
                        break;
                    case 2:
                        e.Value = notInProdListImage;
                        break;
                    case 3:
                        e.Value = workingImage;
                        break;
                }

            }
        }

16.01.2008 - 21:49 Uhr

Gibt es keine andere Möglichkeit dies nach dem Befüllen zu machen?

16.01.2008 - 16:42 Uhr

verwendetes Datenbanksystem: SQL Server Express 2005

Wenn ich mit dem Visual Studio 2005 C# eine SQL-SERVER Datenquelle auswählen will, kann ich dies nur auf eine Datenbankdatei (*.mdf) und nicht auf einen Server - wieso dies?
Da ich auf einen DB-Server bei uns im Netz zugreifen will habe ich bisher die ganze Kommunikation per Hand eingerichtet ... funktioniert alles wunderbar, jdoch würde ich das auch gern mit dem Visual Studio Express 2005 machen ... gibt es da eine Möglichkeit?

16.01.2008 - 15:54 Uhr

Ich habe ein DataGridView.
Eine Spalte "Status" enthält Integerzahlen 0-5.
In Abhängikeit dieser Zahlen soll Bilddateien angezeigt werden.
Ich dachte schon ich habe den richtigen Beitrag gefunden jedoch bringe ich es einfach nicht hin 🤔

DataSource des DataGridViews ist eine Tabelle.
aus dieser lasse ich automatisch das DataGridView erzeugen:


BindingSource BS_Auftraege.DataSource = new DataView(this.myTable);
DataGridView DGV_PanelTypen.DataSource = BS_Auftraege;

Wie kann ich dies nun bewerkstelligen?

Durch das automatische Füllen ist ja die Spalte "Status" (die Integer Werte enthält)
automatisch ein DataGridViewColumn oder?

Hier ein versuch von mir


        private void DGV_PanelTypen_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (DGV_PanelTypen.Columns[e.ColumnIndex] == DGV_PanelTypen.Columns["Status"] )
            {
                Image a = Image.FromFile("D:\\SMA\\PROJECT\\IMAGES\\apply.png");
                Image b = Image.FromFile("D:\\SMA\\PROJECT\\IMAGES\\flash1.png");

                //hier zur Laufzeit ein Fehler da er die impl. Konvert. nicht vornehmen kann?
                switch ((int)e.Value)
                {
                    case 0:
                        DGV_PanelTypen[e.ColumnIndex, e.RowIndex].Value = a;
                        break;
                    default:
                        DGV_PanelTypen[e.ColumnIndex, e.RowIndex].Value = b;
                        break;
                }

            }
        }
16.01.2008 - 11:06 Uhr

Tja ... nachdem ich noch ca. 5 Wochen für das Projekt habe werde ich wohl diese saubere Lösung danach beim nächsten implementieren - jetzt muss ich das ganze mal zum Laufen bringen ... Aller Anfang ist schwer ... besonders beim Programmieren ... wenn Du weißt was ich meine 😉 🙁
Danke für Deine Hilfe!