IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Presentation Foundation Discussion :

Binding sur TextBlock [Débutant]


Sujet :

Windows Presentation Foundation

  1. #1
    Membre régulier
    Profil pro
    Développeur
    Inscrit en
    Mai 2002
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Mai 2002
    Messages : 85
    Points : 105
    Points
    105
    Par défaut Binding sur TextBlock
    Bonjour
    Je tente sans succès depuis des jours, de mettre en place le mécanisme suivant.
    Au chargement de mon appli, j'affiche un splashscreen contenant un TextBlock qui est censé afficher un texte informant du traitement en cours sur la MainWindow (le chargement des données peut prendre plusieurs dizaines de secondes). Je tente d'utiliser le binding pour ça.

    J'ai mis en place le mécanisme suivant.
    Code XAML du splashscreen
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <TextBlock Text="{Binding Path=TexteDeroulement}"/>
    Dans le code-behind du splashscreen
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public partial class FenetreSplashScreen : Window, INotifyPropertyChanged
      {
        public event PropertyChangedEventHandler PropertyChanged;
        private void FirePropertyChanged(string name)
        {
          if (this.PropertyChanged!=null)
          {
            this.PropertyChanged(this, new PropertyChangedEventArgs(name));
          }
        }
     
        private string _TexteDeroulement;
        public string TexteDeroulement
        {
          get { return this._TexteDeroulement; }
          set
          {
            if (this._TexteDeroulement!=value)
            {
              this._TexteDeroulement = value;
              this.FirePropertyChanged("TexteDeroulement");
            }
          }
        }
    Problème, si je mets à jour TexteDeroulement dans la fenêtre Splashscreen, l'affichage se met bien à jour, mais si je le fais dans la mainwindow (à laquelle j'ai passé une référence sur la fenêtre splashscreen), l'affichage ne le prend pas en compte. Et je ne comprends pas pourquoi.
    Quelqu'un peut m'aider ?

  2. #2
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    ce code me semble bon, quel est le code qui passe la référence du window ?
    tu as mis un point d'arret sur le fire dans le set de la propriété pour être sur que tu y passes dans le cas où ca ne marche pas ?
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre régulier
    Profil pro
    Développeur
    Inscrit en
    Mai 2002
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Mai 2002
    Messages : 85
    Points : 105
    Points
    105
    Par défaut
    Oui, j'ai vérifié avec un point d'arrêt.
    La mainwindow et le splashscreen sont créés par code dans le App.xaml.cs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    public partial class App : Application
      {
        private FenetreSplashScreen Splashscreen;
     
        public App()
        {
          this.MainWindow = new FenetrePrincipale();
     
          FenetrePrincipale fenetrePrincipale =(FenetrePrincipale) this.MainWindow;
     
          this.Splashscreen = new FenetreSplashScreen();
          fenetrePrincipale.Splashscreen = this.Splashscreen;
          this.Splashscreen.Show();
        }
     
        protected override void OnStartup(StartupEventArgs e)
        {
          base.OnStartup(e);
     
          this.MainWindow.Show();
     
          this.Splashscreen.Close();
          this.Splashscreen = null;
        }
      }
    Et dans la mainwindow
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public partial class FenetrePrincipale : Window
      {
        private FenetreSplashScreen splashScreen;
        public FenetreSplashScreen Splashscreen { set { splashScreen = value; } }

  4. #4
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    ce code me semble bon aussi
    t'as pas de chance ...



    et donc quand depuis fenetreprincipale tu fais splash.Textederoul = "newvalue" tu passes bien sur le firepropchanged ?
    (il reste ce code que tu nous ne montre pas, genre si c'est depuis un autre thread ca pourrait être logique que ca ne fonctionne pas)

    après tu peux aussi mettre un point d'arret sur le constructeur de splashwindow pour être sur que tu n'y passes qu'une fois
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    49
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 49
    Points : 85
    Points
    85
    Par défaut
    Pourquoi faire du Binding sur un DataContext qui est le composant lui même ? Ou alors avec une DependencyProperty mais surtout pas avec INotifyPropertyChanged


    - Soit tu fait un SplashScreenViewModel (qui implémente INotifyPropertyChanged avec ta propriété dedans), tu définit le DataContext de FenetreSplashScreen -> SplashScreenViewModel et la c'est le MVVM standart (mais pas vraiment d'utilité à ce niveau la de l'application).

    - Soit tu met à jour directement le texte du champ texte dans le code Behind de FenetreSplashScreen via une méthode par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SetTexteDeroulement(string message)
    {
        this.nomDuChampTextDansLeXaml.Text = message;
    }
    En plus tu supprime une variable (_TexteDeroulement) et une propriété (TexteDeroulement) qui n'as pas réellement de raison d'être car elle n'est pas lu ni écrite par un autre biais, et tu n'as plus besoins d'implémenté INotifyPropertyChanged.


    Sinon il n'y as pas une histoire de Thread ou de Task dans ton initialisation ?, si le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.PropertyChanged(this, new PropertyChangedEventArgs(name));
    se déroule dans le contexte d'un autre Thread que celui de l'UI c'est normal que l'UI n'affiche pas la modification.

  6. #6
    Membre régulier
    Profil pro
    Développeur
    Inscrit en
    Mai 2002
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Mai 2002
    Messages : 85
    Points : 105
    Points
    105
    Par défaut
    J'ai essayé la mise à jour comme tu le proposes avec la méthode SetTexteDeroulement, mais même problème, pas d'affichage du texte.

    Après, je ne suis pas certain d'utiliser la bonne méthode pour arriver à mes fins. Je tâtonne. A la base mon problème est que j'ai une mainwindow qui met du temps à charger des données. Je veux afficher une fenêtre en avant-plan qui accueille l'utilisateur, et lui affiche du texte l'informant du déroulement du traitement en cours.

  7. #7
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Citation Envoyé par champy Voir le message
    Pourquoi faire du Binding sur un DataContext qui est le composant lui même ?
    pour éviter d'avoir à nommer des controles et de lier l'interface au code behind ? (même si c'est pas du M et que la classe sert de VM ca reste du code behind)

    Citation Envoyé par champy Voir le message
    Ou alors avec une DependencyProperty mais surtout pas avec INotifyPropertyChanged
    dependency est plus performant (beaucoup ?) ? autre raison ?
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #8
    Membre régulier
    Profil pro
    Développeur
    Inscrit en
    Mai 2002
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Mai 2002
    Messages : 85
    Points : 105
    Points
    105
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    et donc quand depuis fenetreprincipale tu fais splash.Textederoul = "newvalue" tu passes bien sur le firepropchanged ?
    (il reste ce code que tu nous ne montre pas, genre si c'est depuis un autre thread ca pourrait être logique que ca ne fonctionne pas)
    Dans le Window_Loaded de FenetrePrincipale j'instancie une classe qui charge des données, et juste avant je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    splashScreen.TexteDeroulement="blablabla";
    Je ne passe bien qu'une fois dans le constructeur de splashscreen.

    Mon problème me semble basique, mais comme je dis, je ne suis pas certain de le prendre par le bon bout. Je démarre en WPF, et j'ai beaucoup de réflexes winforms. J'essaie de reproduire ce que j'ai déjà fait en winforms, par utilisation de délégués pour la mise à jour de l'affichage. Je pensais qu'en WPF la bonne méthode était celle que je tente de mettre en place. Si je me fourvoie, et qu'il faut faire autrement, n'hésitez pas à me recadrer.

  9. #9
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    si tu parles de délégué c'est que tu es sur un autre thread, auquel cas c'est le même principe, sauf que c'est par dispatcher qu'il faut passer
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  10. #10
    Membre régulier
    Profil pro
    Développeur
    Inscrit en
    Mai 2002
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Mai 2002
    Messages : 85
    Points : 105
    Points
    105
    Par défaut
    Merci pour tes réponses. Je vais regarder de ce côté.

  11. #11
    Membre averti
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Novembre 2014
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2014
    Messages : 196
    Points : 331
    Points
    331
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    pour éviter d'avoir à nommer des controles et de lier l'interface au code behind ? (même si c'est pas du M et que la classe sert de VM ca reste du code behind)


    dependency est plus performant (beaucoup ?) ? autre raison ?
    Si le DataContext est le composant lui-même l'interface graphique est de toute façon lié au code behind, impossible de l'utiliser pour une autre interface graphique étant données que c'est une classe partiel, ce qui n'est pas le cas d'un ViewModel. De plus se nom doit seulement être unique dans le même niveau d’arborescence de l'arbre WPF, nommé un contrôle n'est pas non plus impensable il ne s'agit pas d'un id d'un élément JavaScript qui pourrais rentrer en collision avec un autre élément avec le même id par exemple. D'autant plus dans ce cas, car il faut bien l'avouer une application comporte rarement plusieurs SplashScreen

    Pour DependencyProperty, tu ne verras jamais un contrôle WPF du Framework implémenter INotifyPropertyChange, tous passe systématiquement par des DependencyProperty, et oui c'est aussi pour des raisons de performance, INotifyPropertyChange par définition notifie les changement de valeur de propriétés ce qui, intrinsèquement, inclue un système qui va collecté les propriétés à écouter hors pour tous ce qui hérite de Control (voir plus haut dans la hiérarchie des classe je ne la connais pas par cœur non plus) il y en as déjà un les DependencyProperty, du coup si les deux sont mis en place des itérations inutile vont être effectué.

    Un très bon début pour commencer à créer des Contrôle réutilisable (pas forcément des User Control) est de regarder comment sont fait ceux du Framework et de s'en inspirer car les ingénieurs de chez Microsoft maîtrise mieux leur Framework que moi (et sans trop m'avancer je pense aussi de toi )

  12. #12
    Membre averti
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Novembre 2014
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2014
    Messages : 196
    Points : 331
    Points
    331
    Par défaut
    Pour notifier un changement au Thread de l'UI depuis un autre Thread il faut utiliser le dispatcher :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    System.Windows.Application.Current.Dispatcher.Invoke(new Action(delegate () {               
        this.FirePropertyChanged("TexteDeroulement");
    }));
    Dans une classe qui hérite de Window comme la tienne tu doit même pouvoir faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    this.Dispatcher.Invoke(new Action(delegate () {               
        this.FirePropertyChanged("TexteDeroulement");
    }));

  13. #13
    Membre averti
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Novembre 2014
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2014
    Messages : 196
    Points : 331
    Points
    331
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    si tu parles de délégué c'est que tu es sur un autre thread, auquel cas c'est le même principe, sauf que c'est par dispatcher qu'il faut passer
    Pas forcément les délégués n'ont pas de rapport avec les thread, c'est juste une référence vers une méthode.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
     
        class Program
        {
            //Mon delegate aura exactement la même signature que ma méthode !
            delegate bool PremierDelegate(string i);
     
            static void Main(string[] args)
            {
                //Je crée une variable a qui contiendra la méthode Test.
                PremierDelegate a = new PremierDelegate(Test);
     
                //Au lieu d'appeler Test, je vais appeler a, ce qui me donnera le
                //même résultat !
                bool resultat = a("Ceci est un test qui est négatif !");
                bool res2 = a("Positif");
            }
     
            static public bool Test(string test)
            {
                return test.Length < 15;
            }
        }
    Dans ce code point de notion de Thread, de Task ou autre Paralle en revanche on utilise des délégués.
    D'ailleurs toutes les écoutes d’événements ne sont que des liste de délégués, point de notion de Thread non plus (enfin si en fait mais bien plus tard).

  14. #14
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Je pense que le probleme vient du fait que tes traitements longs dans ta fenetre principale sont sur le threadprincipal, donc le thread de l'UI.

    En gros tu demandes à afficher un changement sauf que le thread traite toujours les données que tu charges. Il te faut faire un appel de ces chargement sur un autre Thread (en utilisant les await async c'est encore plus simple)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     private async void Window_Loaded(object sender, RoutedEventArgs e)
            {
                splashScreen.TexteDeroulement = "blablabla";
     
                await Task.Run(() =>
                {
                    for (int i = 0; i < 15000; i++)
                    {
                        Console.Write("h");
                    }
                });
     
                splashScreen.TexteDeroulement = "Terminé!";
            }
    Par contre tu devrais fermer ton splashScreen à la place du "terminé" et non dans le app.xaml en effet le show va rendre immédiatement la main et donc fermer le splashScreen.

  15. #15
    Membre régulier
    Profil pro
    Développeur
    Inscrit en
    Mai 2002
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Mai 2002
    Messages : 85
    Points : 105
    Points
    105
    Par défaut
    Merci pour toutes ces réponses.
    Je vais m'efforcer de mettre en œuvre la solution proposée par micka132.

  16. #16
    Membre régulier
    Profil pro
    Développeur
    Inscrit en
    Mai 2002
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Mai 2002
    Messages : 85
    Points : 105
    Points
    105
    Par défaut
    Finalement, j'ai trouvé la solution suivante. Dans le code de la fenêtre splashscreen, je mets à jour le texte ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SetTexteDeroulement(string message)
    {
        this.nomDuChampTextDansLeXaml.Text = message;
        Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null);
    }

  17. #17
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Citation Envoyé par zworg Voir le message
    Finalement, j'ai trouvé la solution suivante. Dans le code de la fenêtre splashscreen, je mets à jour le texte ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SetTexteDeroulement(string message)
    {
        this.nomDuChampTextDansLeXaml.Text = message;
        Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null);
    }
    Je n'aime pas trop cette façon de faire, surtout si elle se généralise dans l'application parce que ça masque parfois une mauvaise conception et non compréhension du phénomène.
    Mais si ça t'intéresse voici lien ou la personne le mets dans une méthode d’extension pour se retrouver avec un Refresh à la winForms :
    http://geekswithblogs.net/NewThingsI...-controls.aspx

  18. #18
    Membre régulier
    Profil pro
    Développeur
    Inscrit en
    Mai 2002
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Mai 2002
    Messages : 85
    Points : 105
    Points
    105
    Par défaut
    Citation Envoyé par micka132 Voir le message
    Je n'aime pas trop cette façon de faire, surtout si elle se généralise dans l'application parce que ça masque parfois une mauvaise conception et non compréhension du phénomène.
    Tout à fait d'accord. Je suis preneur d'une autre méthode pour mon problème.

  19. #19
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Citation Envoyé par zworg Voir le message
    Tout à fait d'accord. Je suis preneur d'une autre méthode pour mon problème.
    L'utilisation d'autres threads pour tout ce qui est traitement un peu long (calcul complexe, chargement de donnée...).
    Ca permet au thread principal, donc le thread de l'UI d'être beaucoup plus réactive.
    En winform il y avait deja le backgroundWorker qui apportait une abstraction interressante des threads, mais maintenant avec le await/async c'est carrément presque transparent.
    Mais ça complexifie également le programme dans la mesure ou tu dois gérer le fait que ton interface n'est plus gelée, et donc les utilisateurs peuvent cliquer alors que les données ne sont pas encore là.

    Puis tu remarqueras que tu devrais toujours utiliser le dispatcher dans le cas ou tu souhaites modifier un élément de l'affichage depuis un autre thread, mais là c'est l'utilisation normale du mécanisme.

  20. #20
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut
    bonjour
    En fait vu qu'un SplashScreen sert à faire patienter l'user tout dépendra de la durée nécessaire au chargement de ton appli...
    Une façon de simuler l'affichage du SplashScreen avec un Binding est de créer un nouveau Thread et mettre à jour la prop TexteDeroulement(un simple DependencyProperty) du MainWin...
    La maj du prop TexteDeroulement mettra le TextBlock du SplashScreen si son datacontext est lie au MainWin...


    C'est grâce au Dispatcher de ce nouveau Thread (tout Thread possède un Dispatcher qui lui permet de dialoguer avec le Thread UI ou Thread Application)...
    La class App elle-même se reduit à
    - initialiser le MainWin
    - demarrer la Methode Publique de creation du nouveau Thread

    Precaution :virer le StartupUri de App.aml

    son code xaml App.xaml:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    <Application x:Class="WpfThreading2.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 >
        <!--StartupUri="MyMainWindow.xaml">-->
        <Application.Resources>
     
        </Application.Resources>
    </Application>
    et son code behind .cs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
     
    public partial class App : Application
        {
            private MyMainWindow win = null;
            public App()
            {}
            protected override void OnStartup(StartupEventArgs e)
            {
     
                base.OnStartup(e);
                win = new MyMainWindow();
                this.MainWindow = win;
                win.LongTask();
     
            }
    code xaml du WinMain:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
     
    <Window x:Class="WpfThreading2.MyMainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MyMainWindow" Height="350" Width="525">
        <Grid>
            <Grid.Background>
                <RadialGradientBrush >
                    <GradientStop Offset="0.3" Color="Azure" />
                    <GradientStop Offset="0.6" Color="AntiqueWhite" />
                    <GradientStop Offset="0.9" Color="Gold" />
                </RadialGradientBrush>
            </Grid.Background>
            <TextBlock 
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Foreground="DarkBlue"
                FontSize="48"
                Text="MyMainWindow">
     
            </TextBlock>
        </Grid>
    </Window>
    et son code behind .cs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    namespace WpfThreading2
    {
        /// <summary>
        /// Logique d'interaction pour MainWindow.xaml
        /// </summary>
        public partial class MyMainWindow : Window
        {
            SplashScreen splash = new SplashScreen();
            public MyMainWindow()
            {
                InitializeComponent();
                this.DataContext = this;
                splash.DataContext = this;
                splash.Show();
            }
            public string TexteDeroulement
            {
                get { return (string)GetValue(TexteDeroulementProperty); }
                set { SetValue(TexteDeroulementProperty, value); }
            }
     
            // Using a DependencyProperty as the backing store for TexteDeroulement.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty TexteDeroulementProperty =
                DependencyProperty.Register("TexteDeroulement",
                typeof(string), typeof(MyMainWindow),
                new FrameworkPropertyMetadata("Data is Loading ....!"));
     
     
     
            public void LongTask()
            {
                // Create and start a new thread
                Thread newThread = new Thread(
                   new ThreadStart(
                        delegate
                        {
                            Thread.Sleep(2000);//permet de persister l'affichage initial
                            Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                new Action<string>(SetValueMsg), "Patienter  Data is loaded...!");
                            Thread.Sleep(2000); //simuler tache longue ,en fait depend de SetValueMsg
     
                            Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                       new Action<string>(SetValueMsg), "Termine..App starting ...!");
                            Thread.Sleep(2000);//idem
     
                            Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                         new Action(SetValueClose));//ferme splash
                        }
                        ));
                newThread.SetApartmentState(ApartmentState.STA);
                newThread.IsBackground = true;
                newThread.Start();
     
                // WPF automatically creates a new Dispatcher to manage our new thread. All we have to 
                // do to make our thread functional is ask this Dispatcher to start running
                System.Windows.Threading.Dispatcher.Run();
     
            }
     
            private void SetValueMsg(string  msg)
            {
                this.TexteDeroulement = msg;
            }
     
     
            private void SetValueClose()
            {
                splash.Close();
                splash = null;
                this.Show();
            }
        }
    }
    code xaml du simplistic SplashScreen:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    <Window x:Class="WpfThreading2.SplashScreen"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="SplashScreen" Height="300" Width="300">
        <Grid>
            <Grid>
                <Grid >
                    <Grid.Background>
                        <ImageBrush ImageSource="Images/Penguins.jpg">
     
                        </ImageBrush>
                    </Grid.Background>
                    <TextBlock 
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Foreground="Red" FontSize="24" 
                        Text="{Binding TexteDeroulement}">
                    </TextBlock>
                </Grid>
            </Grid>
        </Grid>
    </Window>
    :

    et son code behind .cs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    namespace WpfThreading2
    {
        /// <summary>
        /// Logique d'interaction pour SplashScreen.xaml
        /// </summary>
        public partial class SplashScreen : Window
        {
            public SplashScreen()
            {
                InitializeComponent();
            }
        }
    }
    bon code.....

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Un Binding sur TextBlock qui avait l'air simple
    Par alexadvance dans le forum Windows Presentation Foundation
    Réponses: 3
    Dernier message: 18/08/2009, 09h57
  2. [TextBlock] Probleme de binding sur du texte formaté
    Par Bruno.Chappe dans le forum Windows Presentation Foundation
    Réponses: 7
    Dernier message: 10/05/2009, 16h03
  3. [xaml] Bind sur le titre d'une page
    Par despeludo dans le forum Framework .NET
    Réponses: 6
    Dernier message: 21/03/2007, 09h07
  4. Méthode Bind sur quoi
    Par frouty dans le forum wxPython
    Réponses: 4
    Dernier message: 18/11/2006, 00h24
  5. binding sur une string
    Par fxp17 dans le forum JSF
    Réponses: 8
    Dernier message: 08/09/2006, 11h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo