C# Fortschrittsbalken mit Countdown verbinden

Nero1

Captain Pro
Registriert
Nov. 2009
Beiträge
3.815
Code:
private void myTimer_Tick(object sender, EventArgs e)
        {
            myTimer.Interval = 1000;                                        //Intervall festsetzen

            int[] Array = { Convert.ToInt32(textBox1.Text) };
            progressBar1.Value += 100 / Array[0];

            [usw...]

Hi Leute,

folgendes Problem, ich arbeite immer noch an meinem Programm, welches nach folgendem Schema abläuft:

Es wird eine Zahl in eine Textbox eingegeben, wenn nicht startet nichts und es kommt eine Fehlermeldung im Textfeld (soweit alles gut^^).
Drückt man auf den Button daneben zählt das Programm in Sekundenschritten von der Zahl bis 0 runter und stoppt dann.

------------------------------------------------------

Nun möchte ich das ganze mit einem Fortschrittsbalken ("progressbar1") verbinden, sodass es die einzelnen Schritte flexibel nach der eingegebenen Zahl aufteilt und eben schrittweise sich der Balken bis zur "0" im Textfeld auffüllt und der Prozess eben zuende ist.

Der Teil Code oben ist mein Produkt mehrerer Versuche gewesen.

Im Prinzip würde der Code ja klappen, wenn sich der Timer, in dem es läuft, sich nicht "neu starten" und wie eine for-Schleife verlaufen würde^^

------------------------------------------------------

Nun meine Frage, wie kann ich es am besten umsetzen, dass sich mein Balken gleichmäßig füllen kann, ohne dass sich das Array resettet, sprich die Anfangszahl gespeichert wird (global?)?

Ich hoffe mal ihr könnt mir helfen :(

Lg Nero
 
Kurze Frage, welchen Sinn hat es die Zahl in ein Array zu packen und dann das Erste Element auszulesen?

Code:
int[] Array = { Convert.ToInt32(textBox1.Text) };
progressBar1.Value += 100 / Array[0];

Würde doch auch so gehen!
Code:
progressBar1.Value += 100 / Convert.ToInt32(textBox1.Text)

Verstehe deine Frage nicht ganz.
 
denis-cubic schrieb:
Kurze Frage, welchen Sinn hat es die Zahl in ein Array zu packen und dann das Erste Element auszulesen?

Code:
int[] Array = { Convert.ToInt32(textBox1.Text) };
progressBar1.Value += 100 / Array[0];

Würde doch auch so gehen!
Code:
progressBar1.Value += 100 / Convert.ToInt32(textBox1.Text)

Verstehe deine Frage nicht ganz.

Mittlerweile habe ich ne andere Lösung gefunden, meine wahr ein wenig unlogisch. Die Idee war (so banal es klingen mag :P) alle Zahlen die im Verlaufe des Countdowns auftreten ins Array zu packen und dann die erste Zahl (und somit das Maximum) als dieses festzulegen. Da sich der Timer aber halt immer selbst resettet, ging net.

Deine Variante hatte ich auch schon implementiert, aber da war immer das Problem, dass ich das im Timer gemacht habe, und somit wurde das Maximum auch immer die neue Zahl, sprich es blieb nicht konstant, was mir im Endeffekt also nichts brachte.
Jetzt habe ich es damit gelöst, dass ich das Maximum zumindest vorerst durch einen extra Button festlege, damit klappt alles wie geplant.

Nur ein Problem bleibt, und zwar (vermutlich durch meinen 1 sec Timer) dass der Ladebalken sich erst ca. die halbe Timerzeit später aktualisiert als die Textbox.

Hier der Code (sorry bisschen viel^^):

Code:
private void myTimer_Tick(object sender, EventArgs e)
        {                      
            myTimer.Interval = 1000;                                        //Intervall festsetzen

            if (textBox1.Text == "" || textBox1.Text == "Zahl eingeben!")
            {                                                               //Runtime-Fehler bei fehlender Eingabe kompensieren
                progressBar1.Value = progressBar1.Maximum;
                progressBar1.Refresh();
                textBox1.Text = "Zahl eingeben!";
                myTimer.Stop();
                button1.Text = "START";
            }

           
            else if (textBox1.Text == "1")                                  //Button -> "START" genau bei Erreichen der 0 und nicht erst danach
            {
                button1.Text = "START";
                button1.Refresh();

                int ZahlEingabe = Convert.ToInt32(textBox1.Text);

                ZahlEingabe -= 1;

                textBox1.Text = ZahlEingabe.ToString();

                progressBar1.Value = progressBar1.Maximum - 1;

                progressBar1.Refresh();

                textBox1.Refresh();
            }

            else if (textBox1.Text == "0")                                  //Stoppen des Countdowns bei 0
            {
                button1.Text = "START";
                progressBar1.Value = progressBar1.Maximum;
                progressBar1.Refresh();
                textBox1.Refresh();
                myTimer.Stop();
            }


            else
            {
                int ZahlEingabe = Convert.ToInt32(textBox1.Text);           //eigentliche Countdown-Funktion

                ZahlEingabe -= 1;

                textBox1.Text = ZahlEingabe.ToString();

                progressBar1.Value = progressBar1.Maximum - ZahlEingabe;
                progressBar1.Refresh();

                textBox1.Refresh();                                
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {

            if (myTimer.Enabled == true)            //Countdown pausieren, außer bei "0"
            {
                myTimer.Stop();
                button1.Text = "Weiter";
                button1.Refresh();

                if (textBox1.Text == "0")
                {
                    button1.Text = "START";
                }
            }

            else                                    //Countdown fortsetzen, außer bei "0"
            {                       
                myTimer.Start();
                button1.Text = "Pause";
                button1.Refresh();
                textBox1.Text = Convert.ToString(textBox1.Text);
                textBox1.Refresh();

                

                if (textBox1.Text == "0")
                {
                    button1.Text = "START";
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            progressBar1.Maximum = Convert.ToInt32(textBox1.Text);  //Maximum des Balkens vordefinieren
        }

Zu den Refresh's, einfach der Sicherheit halber hab ich ein bisschen mehr reingetan um den Fall einer fehlenden Aktualisierung auszuschließen. Die kommen später wieder raus.

Weißt du einen Weg wie ich die Verzögerung raus bekomme?
 
Du solltest erst mal etwas Struktur in deinen Code bringen. Was macht button1 und button2?
Anstatt immer wieder den Text in der TextBox zu parsen wäre eine Instanzvariable int countdown die bessere Wahl. Es sein denn, der Benutzer soll den Wert jederzeit durch ändern des TextBox-Inhalts ändern können.

Bei dem Zustand des Countdown ist es ähnlich. Du unterscheidest zw. "Läuft", "Pause" und "Stop". Dein Button1 behandelt aber nur die ersten beiden Fälle. Eine weitere Variable, die den aktuellen Zustand angibt wäre hier sinnvoll.

Die Abfrage in Zeile 5 muss raus. Was machst du wenn der Benutzer "Hallo" in die Box schreibt? Da muss etwas sinnvolleres hin (siehe Absätze oben).

Warum gibst du dem Timer in Zeile 3 jedes mal sein Intervall vor und nicht einmal beim Initialisieren?
Das Rumgerechne ab Zeile 20 kannst du dir sparen, das Ergebnis ist immer 0. ;)
Zeile 26 verstehe ich nicht. Warum füllst du die ProgressBar kurz vor Ende wieder auf?
Zeile 78 ist redundant.

Warum die ProgressBar verzögert angezeigt wird, kann ich nicht sagen. Kannst du das ganze Projekt mal hochladen?
 
Ok, danke erstmal für die Tipps^^ Mal sehen was ich davon umsetzen kann. Der Sinn der Zeile 26 ist es diese bis dorthin aufzufüllen, da das auffüllen an sich nicht einfach so übergreifend geht glaube ich oder zumindest mit dem Timer ich da keine Möglichkeit sehe^^ Bin relativ neu drin.

Die Verzögerung, habe ich gefunden, liegt an Windows 7. Ab Vista ist diese flexible Anzeige die sich "gescmeidig auffüllt" ^^ Und da rechnet der PC schneller als es das Zeichnen kann, wenn ich das richtig verstanden habe. Aber auf alle Fälle etwas komisch...^^

Projekt hochladen geht erst wenn ich wieder auf Arbeit bin morgen ;)
Ergänzung ()

So, hier ist mal ein aufgefrischter und entmüllter Code:

UPDATE

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;


namespace WindowsFormsTest_Weiterentwicklung
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

               
        private void myTimer_Tick(object sender, EventArgs e)
        {
            myTimer.Interval = 1000;                                        //Intervall festsetzen

            bool zahl = true;
            int nummer = 0;
            foreach (char x in textBox1.Text)
            {
                if (!char.IsDigit(x))
                {
                    zahl = false;
                }
            }

            if (zahl == false)                                                //nur Zahlen erlaubt
            {
                textBox1.Text = "Zahl eingeben!";
                myTimer.Stop();
                btnStart.Text = "START";
            }

            else
            {
                nummer = Convert.ToInt32(textBox1.Text);

                if (nummer > 0)
                {
                    nummer -= 1;
                    textBox1.Text = nummer.ToString();

                    progressBar1.Value = nummer / progressBar1.Maximum;

                    if (nummer == 0)
                    {
                        btnStart.Text = "START";
                    }
                }
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            textBox1.ReadOnly = true;

            if (myTimer.Enabled == true)            //Countdown pausieren
            {
                myTimer.Stop();
                btnStart.Text = "WEITER";

                if (textBox1.Text == "0")           //dauerhaft auf START wenn nummer=0
                {
                    btnStart.Text = "START";
                }
            }
            else                                    //Countdown fortsetzen, außer bei "0"
            {
                myTimer.Start();
                btnStart.Text = "PAUSE";
                textBox1.Text = Convert.ToString(textBox1.Text);

                if (textBox1.Text == "0")           //dauerhaft auf START wenn nummer=0
                {
                    btnStart.Text = "START";
                }
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            myTimer.Stop();
            textBox1.Text = "[Bitte Zahl eingeben]";
            btnStart.Text = "START";
        }

        private void textBox1_Click(object sender, EventArgs e)
        {
            textBox1.SelectAll();
        }

Button 2 (btnStop) wurde entsprechend erweitert um zu stoppen.

Erstmal die Frage, wie bekomme ich es hin vernünftig die Progressbar aufzufüllen? es will einfach nich gehen wie ich es will, obwohl ich verschiedenes ausporbiert hab. Hatte mal was, aber das hab ich aus Versehen gelöscht und mir isses entfallen :D

Is der Code so erstma von der Form her in Ordnung oder gibt es noch was zu verbessern?
und habt ihr eine lösung für die Progressbar?
Ergänzung ()

So, hier ist es.

[Gelöscht, siehe 2 Posts weiter]
 
Zuletzt bearbeitet: (Update)
Aufgrund der Übersicht starte ich hier nochmal ein Feld^^

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;


namespace WindowsFormsTest_Weiterentwicklung
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

               
        private void myTimer_Tick(object sender, EventArgs e)
        {
            myTimer.Interval = 1000;                                        //Intervall festsetzen

            bool zahl = true;
            int nummer = 0;
            foreach (char x in textBox1.Text)
            {
                if (!char.IsDigit(x))
                {
                    zahl = false;
                }
            }

            if (zahl == false)                                                //nur Zahlen erlaubt
            {
                textBox1.Text = "Zahl eingeben!";
                myTimer.Stop();
                btnStart.Text = "START";
            }

            else if (zahl == true)
            {
                nummer = Convert.ToInt32(textBox1.Text);

                if (nummer > 0)
                {
                    nummer -= 1;
                    textBox1.Text = nummer.ToString();

                    progressBar1.Value -= 1;

                    if (nummer == 0)
                    {
                        btnStart.Text = "START";
                    }
                }
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            textBox1.ReadOnly = true;

            bool zahl = true;
            foreach (char x in textBox1.Text)
            {
                if (!char.IsDigit(x))
                {
                    zahl = false;
                }
            }
            if (zahl == false)                                                //nur Zahlen erlaubt
            {
                textBox1.Text = "Zahl eingeben!";
                btnStart.Text = "START";
            }

            if (zahl==true)
            {
                progressBar1.Maximum = Convert.ToInt32(textBox1.Text);
            }
            
            if (myTimer.Enabled == true)            //Countdown pausieren
            {
                myTimer.Stop();
                btnStart.Text = "WEITER";

                if (textBox1.Text == "0")           //dauerhaft auf START wenn nummer=0
                {
                    btnStart.Text = "START";
                }
            }
            else                                    //Countdown fortsetzen, außer bei "0"
            {
                myTimer.Start();
                btnStart.Text = "PAUSE";

                if (textBox1.Text == "0")           //dauerhaft auf START wenn nummer=0
                {
                    btnStart.Text = "START";
                }
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            myTimer.Stop();
            textBox1.Text = "[Bitte Zahl eingeben]";
            btnStart.Text = "START";
            textBox1.ReadOnly = false;
            progressBar1.Value = progressBar1.Maximum;
        }

        private void textBox1_Click(object sender, EventArgs e)
        {
            textBox1.SelectAll();
        }

Ist nun nochmals abgeändeter Code, nonsens rausgepackt, wie
textbox1.text=Convert.toString(textbox1.text); :rolleyes:
und die Progressbar als ablaufendes Medium^^

Sprich die Anzeige sinkt.

Nun habe ich folgendes Problem ganz neuer Art: bsp. ich lasse erst einen Countdown von 20 sec laufen breche ihn beliebig meinetwegen bei 17 sec ab (btnStop). Nun aber gebe ich als neue Zahl 100 ein und starte den Countdown erneut.
Was passiert? --> Die Progressbar springt sozusagen zu dem Value 20 auf der Progressbar und zähl von dort die 100 runter. Das ergibt eine Fehlermeldung wenn man zulange wartet :D

Wie kann ich das verhindern? Bzw. wie kann ich das so einstellen, dass er wieder von "vorn" beginnt? Weiß grad echt nich weiter :(
 

Anhänge

Ich hab dir dein Projekt unten nochmal angehangen. Da stehen eine ganze Menge Kommentare drin. Hauptsächlich ist es das, was Darlis versucht hat dir zu sagen ;)
Lies die einfach mal und versuch den Unterschied zu deinem Code zu erkennen, das ist eigentlich relativ einfach.
Ergänzung ()

Btw. da ist noch eine kleine Schlampigkeit drin ;)
Hinter Zeile 78 kannst du noch folgendes Einfügen:
Code:
progressBar.Value = 0;

Das bewirkt, dass wenn der Timer abgelaufen ist, d.h. deine Zahl bei 0 angekommen ist und du nun eine neue eingibst (ohne vorher Stop gedrückt zu haben), dass die ProgressBar wieder auf 0 zurückspringt (anderfalls bleibt diese immer auf ihrem Maximum hängen).
 

Anhänge

Zuletzt bearbeitet:
Also erstmal vielen Dank für die zahlreichen Kommentare^^ Einige Befehle/Möglichkeiten kannte ich noch gar nicht und werde mir die mal extrahieren^^
Das "Problem", was ich nur, an deinem so unglaublich kurz gefassten Code dass ich mir schon wieder doof vorkomme^^, sehe ist, dass die Progressbar im Gegensatz zu meinem Code verzögert ist und nicht gleichzeitig mit der Ausgabe der Zeit läuft. Wenn du da noch ne Lösung für hättest würde ich niederknien :D

Und ein paar Fragen:

Code:
private void Reset( bool resetProgress )
        {
            myTimer.Stop();
            textboxEingabe.ReadOnly = false;
            btnStart.Text = "START";

            // Bestimmt, ob auch der Inhalt der TextBox und die Progressbar
            // zurückgesetzt werden sollen.
            if ( resetProgress )
            {
                textboxEingabe.Text = "[Bitte Zahl eingeben]";
                progressBar.Value = 0;

Wie wirkt da die if (resetProgress) bzw das resetProgress? Heißt das automatisch wenn resetProgress true ist? Aber wie bestimme ich/das Programm den Zustand? Blicke da nich durch. Heißt das im Endeffekt, wenn im Verlaufe des Codes Reset(true) wird, dann tritt das mit Textbox und progressbar ein?

Code:
bool isNumber = int.TryParse( textboxEingabe.Text, out _number )

wofür steht das out? was macht das genau?

Code:
// Die eingegebene Nummer speichern wir hier.
        private int _number;

        // Ein Boolean, der bestimmt, ob der Timer pausiert wurde.
        private bool _isPaused;

Ok die Frage ist kurz: WIE? :D Entweder bin ich blöd oder ich check nicht wie du das da zuweist, bzw die Zustandsabfrage rausbekommst -.-

Bitte ein paar Erklärungen, ich bin schon echt geflasht, hoffe ich werd auch mal so gut^^

Lg und vielen Dank

EDIT:

Hab ich gemacht, danke ;)

EDIT 2:


hat aber doch keine Möglichkeit, is doch Readonly=true XD
 
Zuletzt bearbeitet:
Nero1 schrieb:
Das "Problem", was ich nur, an deinem so unglaublich kurz gefassten Code dass ich mir schon wieder doof vorkomme^^,

Das ist doch Blödsinn. Der Code ist ja auch gar nicht kurz gefasst. Das einzige was ich gemacht habe, den Code aus dem Timer-TickEventHandler zu entfernen und ihn zu den Buttons zu schieben.
Deine TextBox war ja von vornherein readonly, d.h. Eingaben konnten während der Timer aktiv ist, nicht verändert werden. Da macht es dann auch keinen Sinn ständig das Intervall zu setzen oder zu prüfen, ob man die Eingabe grade parsen kann.
All das passt wunderbar in die Logik für den Start-Button.

Nero1 schrieb:
sehe ist, dass die Progressbar im Gegensatz zu meinem Code verzögert ist und nicht gleichzeitig mit der Ausgabe der Zeit läuft. Wenn du da noch ne Lösung für hättest würde ich niederknien :D

Ist mir nichtmals aufgefallen. Ich schau's mir gleich nochmal an.


Nero1 schrieb:
Und ein paar Fragen:

Code:
private void Reset( bool resetProgress )
        {
            myTimer.Stop();
            textboxEingabe.ReadOnly = false;
            btnStart.Text = "START";

            // Bestimmt, ob auch der Inhalt der TextBox und die Progressbar
            // zurückgesetzt werden sollen.
            if ( resetProgress )
            {
                textboxEingabe.Text = "[Bitte Zahl eingeben]";
                progressBar.Value = 0;

Wie wirkt da die if (resetProgress) bzw das resetProgress? Heißt das automatisch wenn resetProgress true ist? Aber wie bestimme ich/das Programm den Zustand? Blicke da nich durch. Heißt das im Endeffekt, wenn im Verlaufe des Codes Reset(true) wird, dann tritt das mit Textbox und progressbar ein?

Ja, du kannst diese Methode so aufrufen
Code:
Reset( true );
Reset( false );

Wenn du nun 'true' übergibst, werden der Text der TextBox, sowie der Wert der ProgressBar zurückgesetzt. Bei 'false' bleibt die ProgressBar auf ihrem letzten Wert stehen und der Text der TextBox ist ebenfalls unverändert.

Wenn du mal durch den Code schaust. Wenn du Stop klickst wird 'Reset( true );' aufgerufen.
Im EventHandler für den Timer wird geprüft, ob die Zahl größer 0 ist. Wenn nicht, wird 'Reset( false )' aufgerufen. Daher bleibt die ProgressBar grün und in der TextBox steht eine 0, sobald der Countdown beendet wurde.

Nero1 schrieb:
Code:
bool isNumber = int.TryParse( textboxEingabe.Text, out _number )

wofür steht das out? was macht das genau?

Code:
// Die eingegebene Nummer speichern wir hier.
        private int _number;

        // Ein Boolean, der bestimmt, ob der Timer pausiert wurde.
        private bool _isPaused;

Ok die Frage ist kurz: WIE? :D Entweder bin ich blöd oder ich check nicht wie du das da zuweist, bzw die Zustandsabfrage rausbekommst -.-

out. Wahrscheinlich kennst du den Unterschied zwische Werttypen und Referenztypen nicht.

Ein 'int' ist ein Werttyp, d.h. wenn du einen 'int' an eine Methode übergibst, dann gibst du dieser Methode nur eine Kopie, aber nicht die eigentliche Variable. Als Beispiel:

Code:
void Swap( int a, int b )
{
     Console.Out.WriteLine( "a: {0}", a );
     Console.Out.WriteLine( "b: {0}", b );
     int temp = a;
     a = b;
     b = temp;
     Console.Out.WriteLine( "a: {0}", a );
     Console.Out.WriteLine( "b: {0}", b );
}

void DoSwap()
{
    int a = 1;
    int b = 2;
    Swap( a, b );
    Console.Out.WriteLine( "a: {0}", a );
    Console.Out.WriteLine( "b: {0}", b );
}

Dein Programm ruft nun die Methode 'DoSwap' auf. In der Ausgabe erscheint dann folgendes:

Code:
// aus Swap( int a, int b)
a: 1
b: 2
a: 2
b: 1

// aus DoSwap()
a: 1
b: 2

Wie man sieht, werden 'a' und 'b' zwar in 'Swap' getauscht, wenn du dir aber den Inhalt der Variablen nach dem Tausch wieder anzeigen lässt, dann haben sie immer noch ihren ursprünglichen Wert.

Bei Referenztypen (aka Verweistypen) ist das anders. Anstatt einer Kopie wird hier "lediglich" ein Verweis auf den Speicherort der Variablen übergeben. Das führt dann dazu, dass sobald du mit der übergebenen Variable arbeitest, änderst du auch das Original.

In C# gibt es nun die Schlüsselwörter 'out' und 'ref'. Im Grunde machen beide das Gleiche, sie behandeln einen Werttypen wie einen Referenztypen. (Der Unterschied zwischen 'ref' und 'out' ist, dass out der Zahl irgendwas zuweisen muss, während 'ref' die Variable auch ignorieren kann).

Nun zu deiner eigentlichen Frage:

Code:
    private int _number;
    ...
    bool isNumber = int.TryParse( textboxEingabe.Text, out _number )
Zum einen, das 'TryParse' macht genau das, was du in deinem ursprünglichen Code hattest.
Es prüft, ob der übergebene String überhaupt eine Zahl ist. Wenn ja, wird es diesen einlesen und 'true' zurückgeben, wenn nicht, eben 'false'. Gespeichert wird die Zahl in '_number' und weil '_number' vom Typ 'int' ist und 'int' ein Werttyp ist, muss hier ein 'out' vor ('ref' wäre auch möglich, hat Microsoft so aber nicht implementiert (das 'out' garantiert dir auch, dass _number hinterher irgendeinen Wert (0) hat, selbst wenn Parse fehlschlägt)).


Nero1 schrieb:
Bitte ein paar Erklärungen, ich bin schon echt geflasht, hoffe ich werd auch mal so gut^^

Als "so gut" würde ich mich garantiert nicht beschreiben, sonst wäre mir der Fehler mit der ProgressBar nicht unterlaufen :D
Wenn du einfach länger Programmierst, wirst du sehen, dass das von alleine kommt - naja, nicht ganz alleine, aber du wirst Fortschritt machen ;)

Nero1 schrieb:
hat aber doch keine Möglichkeit, is doch Readonly=true XD

Das Betrifft auch nur den Fall, wenn der Countdown durchgelaufen ist und du dann die Zahl änderst.
 
Zuletzt bearbeitet:
holy schrieb:
Als "so gut" würde ich mich garantiert nicht beschreiben, sonst wäre mir der Fehler mit der ProgressBar nicht unterlaufen :D
Wenn du einfach länger Programmierst, wirst du sehen, dass das von alleine kommt - naja, nicht ganz alleine, aber du wirst Fortschritt machen ;)

Ich hoffe es :D

holy schrieb:
Das Betrifft auch nur den Fall, wenn der Countdown durchgelaufen ist und du dann die Zahl änderst.

oh...ups :P

EDIT:

Hab ich glatt das Danke vergessen, sowas :D

Vielen, vielen Dank für die ganzen Tipps, echt super ;) Werde mich wohl noch eine ganze Zeit damit beschäftigen müssen eh ich alles drauf hab^^

Aber auch wenn du nicht der Beste bist (um dir gerecht zu werden xD), du bist mehr als gut genug um viele Level über mir zu spielen und das reicht für meine subjektive Beurteilung mehr als aus um dich als sehr gut zu bezeichnen^^

Danke für die hilfreiche und äußerst schnelle und umfangreiche Antwort, hoffe du (und gern auch andere :D) kannst mir in Zukunft wieder mal helfen ;)

EDIT 2:

Ich bin echt so vergesslich -.-
Wenn du eine Lösung für die Progressbar findest wär nett wenn du mir das noch zeigen könntest ;) Danke^^
Ergänzung ()

Ok (wie oft ich das schon gesagt hab^^),

eine Sache noch, ich hab mich ma belesen und rausgefunden, dass dieser Befehl iwie die Steuerung wieder an die aufrufende Methode zurückgibt.

Kannst du das bitte an folgendem Beispiel mal erklären?

Code:
bool isNumber = int.TryParse(textBoxEingabe.Text, out _number);
            if (!isNumber || _number < 1)
            {
                // falls in der Textbox keine gültige Zahl steht, zeigen wir einen Fehler-Dialog
                MessageBox.Show("Ungültige Eingabe! Bite geben Sie eine positive, ganze Zahl ein.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

Wo "springt" dann die Ausführung nach dem return hin? Oder welche Auswirkung hat das? Ich glaube ich denke falsch o.O
 
Zuletzt bearbeitet:
Nero1 schrieb:
Wenn du eine Lösung für die Progressbar findest wär nett wenn du mir das noch zeigen könntest ;) Danke^^

Ich glaube, da muss dir jemand anderes helfen. Hab da eben nur nochmal kurz drauf geschaut und kann dir wahrscheinlich keine einfache Lösung dafür geben.
Vermutlich hat das irgendwas damit zu tun, wie die ProgressBar ihren Inhalt zeichnet. Wenn man runterzählt, also mit progressBar.Value = _number startet und im Timer dann dann immer 1 abziehst, gibt es diese Verzögerung nicht.

Also,

in Zeile 79 wird aus
Code:
progressBar.Value = 0;
Das hier
Code:
progressBar.Value = _number;

Und in Zeile 31 aus
Code:
progressBar.Value++;

Wird
Code:
progressBar.Value--;

Hab sogar eben gesehen, dass du es in deinem Code genau so rum hattest. Trotzdem, frag mich bitte nicht, wie genau diese Verzögerung zu Stande kommt. Evtl. weiß jemand anders da mehr drüber.
Ergänzung ()

Nero1 schrieb:
Kannst du das bitte an folgendem Beispiel mal erklären?

Code:
bool isNumber = int.TryParse(textBoxEingabe.Text, out _number);
            if (!isNumber || _number < 1)
            {
                // falls in der Textbox keine gültige Zahl steht, zeigen wir einen Fehler-Dialog
                MessageBox.Show("Ungültige Eingabe! Bite geben Sie eine positive, ganze Zahl ein.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

Wo "springt" dann die Ausführung nach dem return hin? Oder welche Auswirkung hat das? Ich glaube ich denke falsch o.O

Das ganze steht ja in der Methode 'OnBtnStartClick'. Das 'return' stellt jetzt sicher, dass bei einer falsche Eingabe der Code darunter (auch in der Methode 'OnBtnStartClick') nicht mehr ausgeführt wird. D.h. die Methode 'OnBtnStartClick' wird verlassen, bevor sie beendet wurde. (hier, weil sonst der Timer mit einer ungültigen Zahl gefüttert werden würde).

Die Frage nach dem wohin ist etwas komplizierter :)
In deinem Projekt gibt es eine Datei 'Program.cs'. In Zeile 18 steht das hier:
Code:
Application.Run(new Form1());

Um es jetzt etwas laienhaft auszudrücken:
Diese Zeile erstellt dir das Form (das Fenster) und behandelt alle Eingaben etc. (das nennt man Message Loop). Sehr, sehr vereinfacht kann man sich das so vorstellen:

Code:
public class Application
{
    public static void Run( Form form )
    {
        while ( !closeButtonPressed )
        {
            // form ausführen
        }
    }
}

Durch das 'return' springt deine Anwendung jetzt zurück in die While-Schleife.
 
Zuletzt bearbeitet:
So ich hab beides mal getestet und mir ist ein "gravierender" Fehler aufgefallen. Ich versuch das mal zu beschreiben.

Mein Beispiel gilt für beide Arten, sprich für + und - Variante der Progressbar.

Für die + Variante:

Gebe ich z.B. 15 ein, lasse den Countdown ein wenig laufen, drücke Pause, dann auf Löschen (sprich Stopp) und gebe dann eine neue Zahl ein, drücke wieder auf Start, dann startet der Countdown wieder bei der vorherigen Zahl und zählt weiter runter.

Die - Variante ist lustiger^^:

Ich gehe in der gleichen Art und Weise vor, dann kommt eine Fehlermeldung bei folgender Stelle

progressBar1.Value--;

--> Der Wert -1 ist für Value ungültig. Value sollte zwischen 'minimum' und 'maximum' liegen.

Egal ob die zweite Zahl größer oder kleiner ist.

Weißt du warum?^^



Die verzögerung könnte ich mir nur so erklären, dass Windows beim Abziehen nicht fließend abzieht sondern einfach zack und weg^^
Ich hatte mich dazu schonmal belesen und es liegt ab Vista daran, dass Windows diese fließenden Übergänge macht bei den Ladebalken. Könnte mir es nur so erklären, dass dieses Abziehen ja sonst in keiner Weise in Windows auftritt und somit auch nie als fließend programmiert wurde. Ist zwar nur eine Theorie, aber das einzig logische für mich.
 
Ich sag ja, ich arbeite schlampig ;)

Code:
_isPaused = false;

Muss noch in die Methode 'Reset' ;)
 
Habe den Fehler behoben, hatte nur in der Reset-Methode wieder auf Value=0 zurückgesetzt, vergessen zu ändern.

Also behoben ;)^^
Ergänzung ()

Ok lol^^ wo genau rein? resetProgress oder normales Reset? und muss das jetzt noch rein oder nicht? xD
Ergänzung ()

Habs eingefügt, musste doch rein^^ Ok dann läuft jetzt alles perfekt, danke für alles :)
 
Nero1 schrieb:
Ergänzung ()

Ok lol^^ wo genau rein? resetProgress oder normales Reset? und muss das jetzt noch rein oder nicht? xD

Es muss da rein, ja, eben genau für den Fall, dass du erst Pausierst und dann Stop klickst.
Bzgl. wohin. Überleg mal kurz, denke, da kommst du auch selber drauf.
Als Tipp, geh einfach mal den Code in 'OnBtnStartClick' durch.

Edit.
OK, geht doch ;)
 
Ach und noch was (ja ich weiß, zu viel^^)

Ich habs grad erst gesehen mit return, Danke :D

Lg
 
@holy(u.a.):

Sag(t) mal, falls du(ihr) das überhaupt liest(lest), kannst(könnt) du(ihr) mir nochmal helfen? (:D)

Würde um das Thema Webpart und CAML geschrieben in C# gehen, dazu solche Sachen wie z.B. RenderContent() und SPGridview.

Habt ihr da etwas Ahnung oder soll ichs gleich lassen?^^ Oder soll ichs einfach mal probieren und euch meinen Code samt Problem in nen Post klatschen? :D

LG
 
Hui so eine schnelle Antwort^^

Also erstmal der Code des Webparts:

Code:
using System;
using System.Data;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace BookSearchProject.SearchWebPart
{
    [ToolboxItemAttribute(false)]
    public class SearchWebPart : WebPart
    {
        protected TextBox textTitle;
        protected TextBox textAuthor;
        protected Button startSearch;

        string Eingabe = "";

        protected SPDataSource datasource;
        //Boolean für Prüfen der Eingabe im Textfeld
        bool isText;

        protected SPGridView spGrid;

        string url="http://vm-cse-bizagi/";

        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            this.textTitle = new TextBox();
            this.textTitle.Columns = 100;
            this.textTitle.MaxLength = 255;
            this.textTitle.Width = 300;
            //this.Controls.Add(new LiteralControl("<div>Titel: "));
            this.Controls.Add(this.textTitle);
            //this.Controls.Add(new LiteralControl("</div>"));

            this.textAuthor = new TextBox();
            this.textAuthor.Columns = 100;
            this.textAuthor.MaxLength = 255;
            this.textAuthor.Width = 300;
            //this.Controls.Add(new LiteralControl("<div>Autor: "));
            this.Controls.Add(textAuthor);
            //this.Controls.Add(new LiteralControl("</div>"));

            this.startSearch = new Button();
            this.startSearch.Text = "Start Search";
            this.Controls.Add(startSearch);

            this.spGrid = new SPGridView();
            this.spGrid.AutoGenerateColumns = false;
            this.spGrid.AllowPaging = true;
            this.spGrid.PageSize = 10;

            BoundField boundField = new BoundField();
            boundField.HeaderText = "ID";
            boundField.DataField = "ID";
            this.spGrid.Columns.Add(boundField);

            boundField = new BoundField();
            boundField.HeaderText = "Buchtitel";
            boundField.DataField = "Title";
            this.spGrid.Columns.Add(boundField);

            boundField = new BoundField();
            boundField.HeaderText = "Untertitel";
            boundField.DataField = "Zusatz";
            this.spGrid.Columns.Add(boundField);

            boundField = new BoundField();
            boundField.HeaderText = "Autor";
            boundField.DataField = "Autor";
            this.spGrid.Columns.Add(boundField);

            //Ausrichtung des Textes (Spaltenüberschriften) nach links
            this.spGrid.HeaderStyle.HorizontalAlign = HorizontalAlign.Left;
            this.Controls.Add(this.spGrid);

            this.datasource = new SPDataSource();
            this.Controls.Add(this.datasource);
        }
        
        protected override void  RenderContents(HtmlTextWriter writer)
        {
            SPSite site = new SPSite(url);
            SPWeb web = site.OpenWeb();
            SPList list = web.Lists["Bücherliste"];

            this.datasource.DataSourceMode = SPDataSourceMode.List;
            this.datasource.SelectCommand =
                        "<View>" +
                            "<ViewFields>" +
                                "<FieldRef Name=\"ID\"/>" +
                                "<FieldRef Name=\"Title\"/>" +
                                "<FieldRef Name=\"Zusatz\"/>" +
                                "<FieldRef Name=\"Autor\"/>" +
                            "</ViewFields>" +
                            "<Query>" +
                                "<OrderBy>" +
                                    "<FieldRef Name=\"ID\" Ascendung=\"True\"/>" +
                                "</OrderBy>" +
                                "<Where>" +
                                    "<Eq>" +
                                        "<FieldRef Name=\"Title\"/>" +
                                        "<Value Type=\"Text\">" + Eingabe + "</Value>" +
                                    "</Eq>" +
                                "</Where>" +
                            "</Query>" +
                        "</View>";

            this.spGrid.AutoGenerateColumns = false;
            this.spGrid.AllowSorting = true;
            this.spGrid.CssClass = "ms-listviewtable";
            this.spGrid.AlternatingRowStyle.CssClass = "ms-alternating";
            this.spGrid.Width = new Unit(50, UnitType.Percentage);
            this.spGrid.GridLines = GridLines.None;
            this.spGrid.HeaderStyle.Font.Bold = true;
            this.spGrid.HeaderStyle.HorizontalAlign = HorizontalAlign.Left;

            this.spGrid.DataSource = this.datasource;
            this.spGrid.DataBind();
            this.spGrid.RenderControl(writer);
            
            //Label um Darstellung etwas zu modifizieren (Umbrüche)
            Label betweenBreak = new Label() { Text = "<br>" };
            Label title = new Label() { Text = "Titel:  <br>" };
            Label author = new Label() { Text = "Autor:  <br>" };
            Label authorLabelBreak = new Label() { Text = "<br>" };
            Label buttonBreak = new Label() { Text = "<br>" };

            title.RenderControl(writer);
            textTitle.RenderControl(writer);

            authorLabelBreak.RenderControl(writer);
            author.RenderControl(writer);
            textAuthor.RenderControl(writer);

            buttonBreak.RenderControl(writer);
            startSearch.RenderControl(writer);
            betweenBreak.RenderControl(writer);

            //wahlweise auch mit dem unteren Code, dabei fehlen jedoch die Zeilenumbrüche und alle Controls werden auf einmal geladen
            /*
            foreach (Control ctrl in Controls)
            {
                writer.Write("");
                ctrl.RenderControl(writer);
                writer.Write("");
            }
            */
        }

        void startSearch_Click(object sender, EventArgs e)
        {            
            if (string.IsNullOrEmpty(textTitle.Text))
            {
                isText = false;
                return;
            }
            else
            {
                isText = true;
            }

            if (isText==true)
            {
                Eingabe = textTitle.Text;           
            }                       
        }
    }
}

Ich hoffe mal du kannst was damit anfangen^^ (Probiere immer mal was aus, sollte dir was auffallen kann es sein ich habs vergessen weg zu machen, aber trotzdem bitte drauf hinweisen :D)

Mein Problem is folgendes:

Ich möchte über Textfelder eine Liste Filtern. Webpart und Quellliste findest du unten im Anhang. Ich bekomme alles hin mittlerweile mit ein paar Webquellen, sprich wenn ich die CAML-Query im Code festlege dann wirds auch super angezeigt.
Nun möchte ich aber mit der Eingabe im Textfeld diese Query dynamisch gestalten, was aber partout nicht klappen will, das Webpart reagiert sozusagen auf den Button überhaupt nicht.

Wenn du also weißt wie ich das variabel umsetzen kann wär ich hocherfreut ^^

LG
 

Anhänge

  • Webpart und Liste.png
    Webpart und Liste.png
    24,3 KB · Aufrufe: 188
Zurück
Oben