Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
SplashScreen - Statustext Updaten
reloop
myCSharp.de - Member

Avatar #avatar-3256.jpg


Dabei seit:
Beiträge: 139

Themenstarter:

SplashScreen - Statustext Updaten

beantworten | zitieren | melden

Hallo liebe Community,

ich habe folgendes Problem:

Ich möchte meiner Application einen "SplashScreen" verpassen. Dafür habe ich meiner Anwendung ein Window mit dem Namen "SplashWindow" hinzugefügt. Dieses Window enthält ein Label mit dem Namen "txtStatus".

Zur Aktualisierung dieses Textes existiert eine Methode:

SplashWindow.xaml.cs


public void SetStatusText(string text)
{
     if (!txtStatus.Dispatcher.CheckAccess ()) { 
            txtStatus.Dispatcher.Invoke ((Action)delegate { SetStatusText(text); });
      return;
   }
   
   txtStatus.Text = text;
}


Nun instanziiere ich im App (Codebehind) wie folgt den SplashScreen & das MainWindow:

App.xaml.cs



SplashWindow _splashWindow;
....OnStartup()
{
   _splashWindow = new SplashWindow();
   _splashWindow.Show();

   var mainWindow = new MainWindow();
   mainWindow.Show();
   mainWindow.OnSetStatus = SetStatusText;
}

private void SetStatusText(string text)
{
    _splashWindow.SetStatusText(text);
}

Soweit so gut, und zum Schluss existiert im Loaded-Event vom MainWindow folgender Aufruf:

MainWindow.xaml.cs


...

public .... Loaded
{
  OnSetStatus("Daten werden geladen...");
  HoleDaten();
  OnSetStatus("Alle Daten wurden erfolgreich geladen.");
}

...

Es funktioniert alles auch soweit, bei dem Aufruf "OnSetStatus" wird der gesamte Code bishin zum "txtStatus.Text = text" durchlaufen. Jedoch updatet sich die Gui erst beim Beenden der OnStartUp-Methode.

Was mache ich falsch?

Ich habe mich an folgendem Beispiel orientiert:

[FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)


Kam jedoch nicht zum gewünschten Ergebnis.

Vielleicht habt ihr ja einen Tipp für mich.

Gruss
private Nachricht | Beiträge des Benutzers
Ayke
myCSharp.de - Member

Avatar #avatar-2293.gif


Dabei seit:
Beiträge: 643
Herkunft: Hamburg

beantworten | zitieren | melden

WPF hat 2 Threads. Einen womit du arbeitest und einen der alles Zeichnet. Damit die Benutzeroberfläche nicht mehr einfriert beim Zeitaufwändigen unterfangen.

Du musst vermutlich die OnStartup Methode von der Application class aufrufen, damit der Zeichenthread startet.

protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
}
private Nachricht | Beiträge des Benutzers
reloop
myCSharp.de - Member

Avatar #avatar-3256.jpg


Dabei seit:
Beiträge: 139

Themenstarter:

beantworten | zitieren | melden

Hallo Ayke,

hat leider keine Veränderung gebracht. Trotzdem danke für die Hilfe!

Hat vielleicht noch jemand eine Idee?

Gruss,
reloop
private Nachricht | Beiträge des Benutzers
Levion
myCSharp.de - Member

Avatar #avatar-3432.png


Dabei seit:
Beiträge: 114

beantworten | zitieren | melden

Also ich bin der Meinung, dass du dein holeDaten() wohl manuell in einen eigenen Thread pusten musst. Soweit ich das erkenne laufen in WPF alle Methode immernoch im GUI-Thread. Wäre ja auch doof wenn nicht, da man ansonsten für jeden Zugriff auf die GUI diesen Handstand machen müsste.

Das kann man auch schön erkennen, wenn man z.B. einen Button mit einem langen Prozess auf die GUI legt, bleibt der Button eingedrückt bis die Aktion abgeschlossen ist.

Oder gibt es ab WPF eine hübschere Variante?

Gruß

Levi

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.Threading;

namespace WpfApplication1
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            new Thread(new ThreadStart(myProcess)).Start();
        }

        private void myProcess()
        {
             for (int i = 0; i < 1000000; i++)
             {
                setStatusText(i.ToString());
             }
        }

        private void setStatusText(string text)
        {
            if (!textBox1.Dispatcher.CheckAccess())
            {
                textBox1.Dispatcher.Invoke(new Action(delegate()
                {
                    textBox1.Text = text;
                }));

                return;
            }

            textBox1.Text = text;
        }
    }
}
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Levion am .
private Nachricht | Beiträge des Benutzers
Ayke
myCSharp.de - Member

Avatar #avatar-2293.gif


Dabei seit:
Beiträge: 643
Herkunft: Hamburg

beantworten | zitieren | melden

Zitat
Das kann man auch schön erkennen, wenn man z.B. einen Button mit einem langen Prozess auf die GUI legt, bleibt der Button eingedrückt bis die Aktion abgeschlossen ist.


Das wäre wohl anderes auch nicht möglich. Der Button wird aber trotzdem neu gezeichnet, auch wenn er so lange verhaart bis die Aktion abgeschlossen ist.
Das sieht man am besten wenn man den GUI Thread arbeiten schickt und dann mit einen anderen Fenster drüber fährt. Bei Windows Forms hast mann dann ein buntes Fenster. Das wird dann aber wahrscheinlich irgendwo in der Milcore Bibliothek geregelt.

Das verhalten ist irgendwie eigenartig. Habe mal in der Main Methode folgendes versucht. Erst wenn die Application Klasse eine "MessageLoop?" erstellt, werden die Fenster aktualisiert. Das hat wohl eher nix wie in meiner vorherigen Vermutung mit den "Zeichenthread" zu tun.

        [System.STAThreadAttribute()]
        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public static void Main() {
            MainWindow window = new MainWindow();
            window.label1.Content = "Me";
            Thread.Sleep(10000);
            //WpfApplication1.App app = new WpfApplication1.App();
            //app.Run();
        }
private Nachricht | Beiträge des Benutzers