Forum: PC-Programmierung Problem mit ShowDialog() in C#


von SeeScharp (Gast)


Lesenswert?

Hallo.

Ich habe seit ein paar Tagen ein blödes Problem in C#.
Mein Testprojekt besteht aus 2 Fenstern.
Fenster 1: Hauptfenster, Button zum Starten einer Berechnung
Fenster 2: Dialogbox mit ProgressBar

Im EventHandler vom Button wird ein neues Fenster2 angelegt und mit 
ShowDialog() geöffnet.
Die Progressbar läuft bis 100% durch und Fenster2 beendet sich dann 
selbst mit this.DialogResult = true;
Alles OK.

Wird der Button ein weiteres mal gedrückt, bekomme ich bei 
this.DialogResult = true eine Exception:

"DialogResult can be set only after Window is created and shown as 
dialog."


Was mache ich falsch?


Fenster2 C#:
1
namespace WPFProgressbar
2
{
3
    public partial class MyProgressBar : Window
4
    {
5
        public MyProgressBar()
6
        {
7
            InitializeComponent();
8
            TheProgressBar.Value = 0;
9
        }
10
11
        private void ProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
12
        {
13
            if (TheProgressBar.Value >= 100)
14
            {
15
                this.DialogResult = true;
16
            }
17
        }
18
    }
19
}

Fenster2 XAML:
1
<Window x:Class="WPFProgressbar.MyProgressBar"
2
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4
        Title="MyProgressBar" Height="100" Width="300" ResizeMode="NoResize">
5
    <StackPanel>
6
        <Label>Processing...</Label>
7
        <ProgressBar x:Name="TheProgressBar" Height="20" Value="{Binding CurrentValue}" Minimum="0" ValueChanged="ProgressBar_ValueChanged" Maximum="100"></ProgressBar>
8
    </StackPanel>
9
</Window>

Fenster1 C#:
1
namespace WPFProgressbar
2
{
3
    public partial class MainWindow : Window, INotifyPropertyChanged
4
    {
5
        private int _currentValue;
6
        public int CurrentValue
7
        {
8
            get { return _currentValue; }
9
            set 
10
            { 
11
                _currentValue = value;
12
                if (PropertyChanged != null)
13
                {
14
                    PropertyChanged(this, new PropertyChangedEventArgs("CurrentValue"));
15
                }
16
            }
17
        }
18
19
        public MainWindow()
20
        {
21
            InitializeComponent();
22
        }
23
24
        void AsyncFunction()
25
        {
26
            Thread.Sleep(1000);
27
            for (int i = 1; i <= 100; ++i)
28
            {
29
                Thread.Sleep(10);
30
                CurrentValue++;
31
            }
32
        }
33
34
        private void ButtonClick(object sender, RoutedEventArgs e)
35
        {
36
            CurrentValue = 0;
37
38
            MyProgressBar ProgressView = new MyProgressBar();
39
            ProgressView.DataContext = this;
40
41
            Thread t = new Thread(new ThreadStart(AsyncFunction));
42
            t.Start();
43
44
            ProgressView.ShowDialog();
45
        }
46
47
        public event PropertyChangedEventHandler PropertyChanged;
48
    }
49
}

Fenster1 XAML:
1
<Window x:Class="WPFProgressbar.MainWindow"
2
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4
        Title="MainWindow" Height="350" Width="525">
5
    <StackPanel>
6
        <TextBox x:Name="LogTextBox" Margin="5" IsEnabled="False"></TextBox>
7
        <Button Margin="5" Click="ButtonClick">Start Processing</Button>
8
    </StackPanel>
9
</Window>

von Peter II (Gast)


Lesenswert?

SeeScharp schrieb:
> this.DialogResult = true;

sieht komisch aus. Wie soll sich damit ein Fenster schließen?

Normalweise setzt man dort den ResultStatus

DialogResult == DialogResult.OK

dann kann man das Fenster mit Close schließen. Nur musst du es wieder 
ordentlich anlegen.

Eigentlich schreibt man dann immer:

Form pv = new ProgressView();
pv.ShowDialog();

von SeeScharp (Gast)


Lesenswert?

Peter II schrieb:
> Normalweise setzt man dort den ResultStatus
>
> DialogResult == DialogResult.OK
>

Der Datentyp den mir VS2013 anzeigt ist ein bool? .
DialogResult.OK gibt es bei mir nicht? Was mache ich falsch?

> dann kann man das Fenster mit Close schließen. Nur musst du es wieder
> ordentlich anlegen.
> Eigentlich schreibt man dann immer:
>
> Form pv = new ProgressView();
> pv.ShowDialog();

Ob ich jetzt die Basisklasse Form oder meine Klasse MyProgressBar nehme, 
sollte doch keinen unterschied machen oder?

von Marcus W. (Gast)


Lesenswert?

Hast du die richtigen "using"-Direktiven in der Klasse festgelegt? Sonst 
musst du mit dem kompletten Pfad auf das Enum "DialogResult" zugreifen.

von SeeScharp (Gast)


Lesenswert?

Wie würde die "richtige" using Direktive lauten?

Ich habe mir die Klasse System.Windows.Window angesehen, welche ja die 
Basisklasse für beide Fenster darstellen.
Da wird auch der Datentyp bool? verwendet.
1
public bool? DialogResult { get; set; }

von SeeScharp (Gast)


Lesenswert?

Ich verwende WPF und nicht WinForms, desshalb kein DialogResult.OK...
Aber das Problem bleibt...

von Borislav B. (boris_b)


Lesenswert?

Um mal ein bisschen zu raten:

Probier mal

DialogResult = true;
this.Close();

um die Form zu schließen.
Oder setz das DialogResult im Konstruktor auf null...

oder mach mal ein using(){} um deine ProgressBar...

von Oliver R. (superberti)


Lesenswert?

Es ist etwas unglücklich, dass Dein Dialog nach dem Drücken des Knopfes 
nur noch durch das XAML-Binding die Verbindung zu Deinem Hauptfenster 
hat. Diese wird aber niemals gelöst, sondern der Dialog lebt stets 
weiter, da durch das Binding der GC das Teil nicht abräumen kann.
Beim zweiten Auslösen hast Du deshalb ZWEI Dialoge als lebende Objekte. 
Beide werden durch das Binding Value="{Binding CurrentValue}" über eine 
Veränderung des ProgressBar-Wertes informiert.
Der erste ist allerdings gar nicht mehr sichtbar und wurde schon ein mal 
angezeigt. Vollkommen zu recht bekommst Du vom ersten Dialog deswegen 
diese Exception.

Gruß,
Oliver

von SeeScharp (Gast)


Lesenswert?

Vielen Dank.

Ich hab sowas in die Richtung vermutet, aber auf das Databinding hab ich 
nicht gedacht.
Jetzt setze ich den DataContext auf NULL, nachdem der Dialog beendet 
wird und es funktioniert.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.