none
Actualisation d'un controle après un evenement (iNotifyPropertyChanged) RRS feed

  • Question

  • Bonjours !!!

     

    Je suis novice dans le domaine, et je suis entrain de travailler sur un projet, et pour ma classe principal j'utilise l'INotifyPropertyChanged pour attacher un evenement au changement de mes variables.

     

    J'ai une classe "Contexte", qui contient la variable a afficher:

        public class Contexte : MainWindow
        {
            private string noms;
            public string Noms
            {
                get
                {
                    return noms;
                }
                set
                {
                    if (value == noms)
                        return;
                    noms = value;
                    NotifyPropertyChanged("Noms");
                }
            }
        }


    Et ma classe MainWindow de la fenêtre principale:

     

        public partial class MainWindow : Window, INotifyPropertyChanged
        {
            private static Contexte contexte;
    
            int index = 0;
    
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void window_Loaded(object sender, RoutedEventArgs e)
            {
                contexte = new Contexte
                {
                    Noms = "Alpha PREMIER"
                };
     
                DataContext = contexte;
            }
    
            private void buttonUpdate_Click(object sender, RoutedEventArgs e)
            {
                contexte.Noms = "Julien DUBOIS";
            }
     
            public void updateView()
            {
                TextBlock_Titre.Text = "Profil de JULIEN";
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
            public void NotifyPropertyChanged(string nomPropriete)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(nomPropriete));
                     updateView();
                }
            }
        }
    


    Et le code XAML de MainWindow

     

        <Grid>
            <StackPanel HorizontalAlignment="Left" Margin="10,10,0,10" Width="200">
                <TextBlock  name="TextBlock_Titre" Height="25"/>
                <TextBlock Text="{Binding Noms}" Height="25"/>
            </StackPanel>
            <TextBox Name="textBox_index" HorizontalAlignment="Left" Height="23" Margin="215,10,0,0" Text="0" VerticalAlignment="Top" Width="100"/>
            <Button Content="Update" Click="buttonUpdate_Click" HorizontalAlignment="Left" Margin="215,38,0,0" VerticalAlignment="Top" Width="100"/>
        </Grid>

     

    Le problème est qu'après clique sur le bouton "Update", l'interface est automatiquement mise à jours, mais le titre (TextBlock_Titre) ne change toujours pas.

    Merci++ pour votre aide ;)


    JVnal

    lundi 9 septembre 2013 12:38

Réponses

  • Bonjour,

    Dans ce cas ajoutez une propriété Titre dans votre ViewModel :

    public class MyModel
    {
       public string Titre
       {
          get { return this.titre; }
          set
          {
              if (this.titre != value)
              {
    	      this.OnPropertyChanged("Titre");
    
                  this.titre = value;
              }
          }
       }
    }
    
    

    Au niveau de la propriété Noms, changez la propriété Titre comme vous les souhaitez :

     public string Noms
            {
                get { return _noms; }
                set
                {
                    _noms = value;
                    OnPropertyChanged("Noms");
                    this.Titre = "Titre : " + value;
                }
            }
    

    Au niveau XAML il suffit de binder votre Titre à votre ViewModel :

    <TextBlock Text="{Binding Titre}" Height="25"/>
    

    C'est cette approche qui faut adopter...

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte logiciel/Consultant/Formateur Freelance
    Blog : http://gilles.tourreau.fr
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0

    • Marqué comme réponse Aurel Bera mardi 10 septembre 2013 11:30
    lundi 9 septembre 2013 22:27
    Modérateur
  • Franchement, une fois que vous aurez commencé avec cette approche, vous aurez du mal à vous en passer.

    NB : j'insiste mais la classe ViewModel ne doit surtout pas hériter de Window (notamment pour les tests unitaires)


    Richard Clark
    Consultant - Formateur .NET
    http://www.c2i.fr
    Depuis 1996: le 1er site .NET francophone

    • Marqué comme réponse Aurel Bera mardi 10 septembre 2013 11:30
    mardi 10 septembre 2013 06:55

Toutes les réponses

  • Votre classe contexte n'a pas à hériter de Window :

       public class MyModel : INotifyPropertyChanged
        {
            private string _noms;
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
    
            public string Noms
            {
                get { return _noms; }
                set
                {
                    _noms = value;
                    OnPropertyChanged("Noms");
                }
            }
        }

    Ensuite, dans le code de votre Window :

        public partial class MainWindow 
        {
            public MainWindow()
            {
                InitializeComponent();
                DataContext = new MyModel {Noms = "Julien"};
            }
    
            private void buttonUpdate_Click(object sender, RoutedEventArgs e)
            {
                ((MyModel) DataContext).Noms = "Toto";
            }
        }


    Richard Clark
    Consultant - Formateur .NET
    http://www.c2i.fr
    Depuis 1996: le 1er site .NET francophone

    lundi 9 septembre 2013 14:07
  • Dans ce sens là, ça marche mais ce que je voudrais, c'est de pouvoir modifier un autre élément (dans mon cas le "TextBlock_Titre") de la fenêtre principal dès qu'il y a changement de ma variable.

    C'est pour cette raison même que j'ai fais hériter ma classe "Contexte" de la classe "MainWindow" pour avoir accès aux éléments de l'interface principal "MainWindow.xaml".

    En optant pour cette solution, je n'aurais plus accès aux contrôles de la fenêtre "MainWindow".

    Merci Richard Clark pour ta contribution ;)


    JVnal

    lundi 9 septembre 2013 16:25
  • Bonjour,

    Dans ce cas ajoutez une propriété Titre dans votre ViewModel :

    public class MyModel
    {
       public string Titre
       {
          get { return this.titre; }
          set
          {
              if (this.titre != value)
              {
    	      this.OnPropertyChanged("Titre");
    
                  this.titre = value;
              }
          }
       }
    }
    
    

    Au niveau de la propriété Noms, changez la propriété Titre comme vous les souhaitez :

     public string Noms
            {
                get { return _noms; }
                set
                {
                    _noms = value;
                    OnPropertyChanged("Noms");
                    this.Titre = "Titre : " + value;
                }
            }
    

    Au niveau XAML il suffit de binder votre Titre à votre ViewModel :

    <TextBlock Text="{Binding Titre}" Height="25"/>
    

    C'est cette approche qui faut adopter...

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte logiciel/Consultant/Formateur Freelance
    Blog : http://gilles.tourreau.fr
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0

    • Marqué comme réponse Aurel Bera mardi 10 septembre 2013 11:30
    lundi 9 septembre 2013 22:27
    Modérateur
  • En fait, l'exemple de code que j'ai posté est un cas très simplifié de mon problème. Dans mon vrai cas, je modifie plein des contrôles (des modifications très personnalisées) appartenant directement à la fenêtre principale (MainWindow). Et pour dire vrai, ça serait un vrai travaille de titan de tout mettre en binder.

    Il n'y aurait donc pas de solution pour mon cas?

    Mais merci Giles pour ta contribution ;)


    JVnal

    mardi 10 septembre 2013 06:25
  • Franchement, une fois que vous aurez commencé avec cette approche, vous aurez du mal à vous en passer.

    NB : j'insiste mais la classe ViewModel ne doit surtout pas hériter de Window (notamment pour les tests unitaires)


    Richard Clark
    Consultant - Formateur .NET
    http://www.c2i.fr
    Depuis 1996: le 1er site .NET francophone

    • Marqué comme réponse Aurel Bera mardi 10 septembre 2013 11:30
    mardi 10 septembre 2013 06:55
  • Ok, merci pour votre aide, je pense que je vais m'y mettre pour faire passer toutes les modifications de l'interface principale par le "binding", c'est un travaille de malade, mais je pence m'y mettre.

    Merci ++ pour votre aide ;)


    JVnal

    mardi 10 septembre 2013 10:05
  • Bonjour

    Merci de votre retour,

    Cordialement,


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    mardi 10 septembre 2013 11:31