Autor Beitrag
Oppi35
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 95
Erhaltene Danke: 3



BeitragVerfasst: Fr 11.03.11 23:56 
Hallo Zusammen,

ich habe in meiner Anwendung ein Hauptfenster und ein Fenster, dass lediglich eine Progressbar enthält.

Das Fenster mit der Progressbar rufe ich dann mit ...ShowDialog() auf.

Nur klappt jetzt das Update der Progressbar nicht mehr. Kann mir jemand sagen, wie ich in einem gestarteten modalen Dialogfeld Properties ändern kann?

Nur zur Info: Wie ich eine Anwendung mit Progressbar z.B. mit Backgroundworker ohne Einfrieren am Laufen halte, weiß ich, nur halt nicht mit einem modalen Dialog.

Gruß
Frank


Moderiert von user profile iconKha: Topic aus WinForms verschoben am Sa 12.03.2011 um 13:18
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4796
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 12.03.11 10:29 
Hallo,

ein modales Fenster ist dann aber der falsche Weg, denn die aufrufende Form arbeitet erst weiter, wenn das Fenster wieder geschlossen wird (denn den Code zum Verändern der ProgressBar hast du doch in der Hauptform, oder?).

Der Ansatz mit dem Backgroundworker ist genau richtig.

Was genau willst du denn programmieren?
Oppi35 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 95
Erhaltene Danke: 3



BeitragVerfasst: Sa 12.03.11 13:34 
Hallo Th69,

vielen Dank für Deine Hilfe.

Richtig, der Code ist in der Hauptform. Grundgedanke war, dass sich bei einer längeren Rechenarbeit die Progressbar in einem neuen Fenster öffnet und während der Berechnung auch im Vordergrund verweilt. Das Hauptfenster soll in dieser Zeit auch gesperrt werden. Das ist doch in vielen Anwendungen so. Allerdings weiß ich nicht, ob dies über modale Dialogfenster gesteuert wird. Lt. Deiner Mail scheinbar nicht.

Also müsste ich dann in WPF z.B. die TopMost Property auf True setzen und das Hauptformular ggfs. für Eingaben während der Berechnung manuell mit Code sperren?! Ich bin davon ausgegangen, ich könnte mir dies mit einem Modalen Dialog etwas vereinfachen:)

Gruß
Frank
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Sa 12.03.11 13:46 
Ich glaube eher, Th69 hat dich missverstanden; jedenfalls sollte es der ProgressBar ziemlich egal sein, ob sie nun auf einem modalen oder nichtmodalen Fenster sitzt :nixweiss: . Ohne Code und eine genauere Beschreibung als "klappt nicht" kommen wir also wahrscheinlich nicht weiter.

/Edit: Vielleicht die wichtigste Frage: Wo und wie wird das Update der ProgressBar ausgelöst?

_________________
>λ=
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4796
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 12.03.11 13:55 
Hallo zusammen,

nein, ich habe es nicht mißverstanden. ;-)

Nur warum postet du (Oppi35) im WinForms-Forum, wenn du jetzt von WPF schreibst.

Generell gilt aber für beide: einfach die Enabled (bzw. IsEnabled) - Eigenschaft der Hauptform während der Berechnung (und Aktualisierung der ProgressBar) im BackgroundWorker deaktivieren (false) und nach getaner Arbeit (im BackgroundWorker.RunWorkerCompleted-Ereignis) wieder aktivieren (true).
Aber wie schon geschrieben, die ProgressBar-Form nur mittels Show() aufrufen (bzw. besser sogar mittels Show(this), damit das Hauptform als Owner dem SubForm übergeben wird - dann brauchst du auch nicht TopMost zu setzen)!

Für diesen Beitrag haben gedankt: Oppi35
Oppi35 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 95
Erhaltene Danke: 3



BeitragVerfasst: Sa 12.03.11 14:23 
Hallo Zusammen,

Th69:
Es ging nicht speziell um Windows Forms. Mir ging es um die grundsätzliche Vorgehensweise. Mit Deinem letzten Posting ist die Sache für mich jetzt absolut einleuchtend. Werde jetzt genau so vorgehen. Vielen Dank für Deine Hilfe.

Kha:
Auch Dir vielen Dank für die Hilfe.

Es reicht 2 Forms zu erstellen (Form1 und Form2). In Form2 existiert eine Progressbar (progressbar1).

In Form1 ruft man folg. Code auf:
ausblenden C#-Quelltext
1:
2:
3:
Form2 form2=new Form2;
form2.ShowDialog();
form2.progessbar1.Value=50//die Progressbar muss public gesetzt sein


Ergebnis:
Die Progressbar wird nicht auf 50 gesetzt, da der Code erst weiter läuft, wenn der Dialog geschlossen wird.

Ich habe vor meinem Posting auch alles durch-gegoogeled. Die Frage gab es häufiger, aber keiner der abgedruckten Codes hat wirklich funktioniert. Ich gehe davon aus, dass der Zugriff auf ein modales Fenster während ShowDialog() nicht möglich ist.

Die Ausführungen von Th69 reichen mir. Solltest Du allerdings einen Weg finden, wie man doch ein modales Fenster "manipulieren" kann, würde mich dies interessieren.

Also nochmal vielen Dank Euch Beiden.

Gruß
Frank

Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Sa 12.03.11 14:32 
user profile iconOppi35 hat folgendes geschrieben Zum zitierten Posting springen:
Ergebnis:
Die Progressbar wird nicht auf 50 gesetzt, da der Code erst weiter läuft, wenn der Dialog geschlossen wird.
Das ist das Resultat davon, dass du UI und Logik nicht ausreichend trennst (dass du die ProgressBar auf public setzen musstet, was schon der erste Hinweis ;) ). Wenn du die Berechnung von der Hauptform löst und in einem BackgroundWorker der Subform ausführst, kann dieser problemlos die ProgressBar aktualisieren.

user profile iconOppi35 hat folgendes geschrieben Zum zitierten Posting springen:
Die Ausführungen von Th69 reichen mir.
Das exakte Verhalten eines modalen Fenster wirst du aber nicht erreichen.

user profile iconOppi35 hat folgendes geschrieben Zum zitierten Posting springen:
Es ging nicht speziell um Windows Forms. Mir ging es um die grundsätzliche Vorgehensweise.
Habe den Thread bereits verschoben, aber dann ist es ja egal.

_________________
>λ=
Oppi35 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 95
Erhaltene Danke: 3



BeitragVerfasst: Sa 12.03.11 15:13 
Hallo Kha,

dann ist hier jetzt doch mein Code:) Meines Erachtens geht es nicht.

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.ComponentModel;
using System.Threading;


namespace WpfApplication6
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    delegate void CopyDelegate();
    delegate void UpdateProgressDelegate(int prozent);
    
    public partial class MainWindow : Window
    {
        private FolderBrowserDialog folderBrowserDialog;
        private List<string> files;
        private Fortschrittsbalken fortschrittsbalken;
        private BackgroundWorker backgroundWorker;
        private UpdateProgressDelegate updateprogressdel;
        private Thread theThread;
        
        public MainWindow()
        {
            InitializeComponent();
            lbl_Quellordner.Content = "";
            lbl_Zielordner.Content = "";
            folderBrowserDialog = new FolderBrowserDialog();
            files = new List<string>();
            updateprogressdel = new UpdateProgressDelegate(updateProgress);
            
            //Backgroundworker
            backgroundWorker = new BackgroundWorker();
            backgroundWorker.WorkerReportsProgress = true;
            backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
            backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
            
            UpdateUI();
            
        }
        private void updateProgress(int prozent)
        {
            fortschrittsbalken.processvalue = prozent;
        }
        void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Debug.WriteLine("Prozent: " + e.ProgressPercentage.ToString());
            //this.Dispatcher.BeginInvoke(updateprogressdel, e.ProgressPercentage);
            fortschrittsbalken.processvalue = e.ProgressPercentage;
            System.Windows.Forms.Application.DoEvents();
            //System.Windows.Forms.MessageBox.Show("In Methode ProcessChanged");
        }

        void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            fortschrittsbalken.Close();
            this.IsEnabled = true;
            this.Visibility = Visibility.Visible;
            //System.Windows.Forms.MessageBox.Show("In Methode RunWorkerCompleted");
        }

        void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            int counter = 0;
            foreach (string str in files)
            {
                backgroundWorker.ReportProgress(counter);
                counter++;
            }
        }

        private void btn_Quellordner_Click(object sender, RoutedEventArgs e)
        {
            if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                cmb_Extension.Items.Clear();
                lbl_Quellordner.Content = folderBrowserDialog.SelectedPath;
                foreach (string str in Directory.GetFiles(folderBrowserDialog.SelectedPath))
                {
                    if (!cmb_Extension.Items.Contains(System.IO.Path.GetExtension(str)))
                    {
                        cmb_Extension.Items.Add(System.IO.Path.GetExtension(str));
                    }
                }
                
                UpdateUI();
            }
        }

        private void btn_Zielordner_Click(object sender, RoutedEventArgs e)
        {
            if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                lbl_Zielordner.Content = folderBrowserDialog.SelectedPath;
                UpdateUI();

            }
        }
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            lbl_Quellordner.Content = "";
            lbl_Zielordner.Content = "";
            cmb_Extension.Items.Clear();
            files.Clear();
            UpdateUI();
        }

        private void UpdateUI()
        {
            if (lbl_Quellordner.Content.ToString() != "" && lbl_Zielordner.Content.ToString()!="")
            {
                btn_Start.IsEnabled = true;
            }
            else
            {
                btn_Start.IsEnabled = false;
                
            }
        }

        private void btn_Start_Click(object sender, RoutedEventArgs e)
        {
            files.Clear();
            foreach (string str in Directory.GetFiles(lbl_Quellordner.Content.ToString()))
            {
                if (cmb_Extension.SelectedItem.ToString()==System.IO.Path.GetExtension(str))
                {
                    files.Add(str);
                }
            }
            this.IsEnabled = false;
            fortschrittsbalken = new Fortschrittsbalken();
            fortschrittsbalken.progressBar1.Minimum = 0;
            fortschrittsbalken.progressBar1.Maximum = files.Count - 1;
            fortschrittsbalken.progressBar1.Value = 0;
            backgroundWorker.RunWorkerAsync();
            
            fortschrittsbalken.ShowDialog();
            
        }
    }
}
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Sa 12.03.11 17:07 
Habe deinen Code wie folgt vereinfacht, ProgressBar läuft einwandfrei durch :nixweiss: :
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
  public partial class MainWindow : Window
  {
    private List<string> files;
    private Fortschrittsbalken fortschrittsbalken;
    private BackgroundWorker backgroundWorker;

    public MainWindow()
    {
      InitializeComponent();
      files = new List<string>();

      //Backgroundworker
      backgroundWorker = new BackgroundWorker();
      backgroundWorker.WorkerReportsProgress = true;
      backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
      backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
      backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);

    }

    void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
      fortschrittsbalken.progressBar1.Value = e.ProgressPercentage;
    }

    void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      fortschrittsbalken.Close();
    }

    void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
      int counter = 0;
      foreach (string str in files)
      {
        backgroundWorker.ReportProgress(counter);
        Thread.Sleep(1000);
        counter++;
      }
    }

    private void btn_Start_Click(object sender, RoutedEventArgs e)
    {
      files.Clear();
      foreach (string str in Directory.GetFiles(@"C:\"))
      {
          files.Add(str);
      }
      fortschrittsbalken = new Fortschrittsbalken();
      fortschrittsbalken.progressBar1.Minimum = 0;
      fortschrittsbalken.progressBar1.Maximum = files.Count - 1;
      fortschrittsbalken.progressBar1.Value = 0;
      backgroundWorker.RunWorkerAsync();

      fortschrittsbalken.ShowDialog();
    }
  }


Meine Behauptung, dass der BackgroundWorker in der modalen Form ausgeführt werden müsse, ist natürlich Unsinn, da er nicht an eine Form, sondern an den SynchronizationContext gebunden ist. Trotzdem ist es immer ratsam, eine starke Kupplung von Forms (und natürlich ganz allgemein) zu vermeiden :) .

_________________
>λ=

Für diesen Beitrag haben gedankt: Oppi35