Wpf problème avec usercontrol créer en temps réel...

Signaler
Messages postés
42
Date d'inscription
mardi 11 décembre 2018
Statut
Membre
Dernière intervention
28 juillet 2020
-
Messages postés
14922
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
26 octobre 2020
-
Bonjour, Je vous sollicite une nouvelle fois, c'est pas faute d'avoir chercher un peu partout mais je ne trouve pas de solution a mon problème.
Dans mon application l'utilisateur peut ajouter des usercontrol via un bouton (rien d'extraordinaire).
j'utilise une observable collection pour remplir une datagrid , mes usercontrol sont aussi bindé à cette observable collection .
Dans mon usercontrol j'utilise l'observable collection ainsi:
 [Serializable]
    public partial class BlockDirect : UserControl, ISerializable, INotifyPropertyChanged
    {

        MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
        public BlockDirect()
        {
            InitializeComponent();
            WireBox.Foreground = Brushes.Black;
            BlockBox.Foreground = Brushes.Black;
            TotalMulti.Foreground = Brushes.Black;
            MainWindow.ListFixture.CollectionChanged += ListFixture_CollectionChanged;
            DataContext = this;
        }
       
       
        public void GenerePropertyChanged(params string[] Props)
        {
            foreach (string p in Props)
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
        }

       
      public  void ListFixture_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
           
                    if (e.NewItems != null)
                        foreach (Fixture item in e.NewItems)
                            item.PropertyChanged += Fixture_PropertyChanged;

                    if (e.OldItems != null)
                        foreach (Fixture item in e.OldItems)
                            item.PropertyChanged -= Fixture_PropertyChanged;
        }
       

        public void Fixture_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Fixture test = sender as Fixture;
           switch (e.PropertyName)
            { 
                case "CircuitNumber" :

                    if (test.CircuitNumber == 1)
                    {
                        GenerePropertyChanged("Filtres1");
                        GenerePropertyChanged("SommeCircuit1");
                    }

                    if (test.CircuitNumber == 2)
                    {
                        GenerePropertyChanged("Filtres2");
                        GenerePropertyChanged("SommeCircuit2");
                    }

                    if (test.CircuitNumber == 3)
                    {
                        GenerePropertyChanged("Filtres3");
                        GenerePropertyChanged("SommeCircuit3");
                    }
                }
                    break;

                case "CircuitName":
                    if (test.CircuitNumber == 1)
                    {
                        GenerePropertyChanged("Filtres1");
                        GenerePropertyChanged("SommeCircuit1");
                    }

                    if (test.CircuitNumber == 2)
                    {
                        GenerePropertyChanged("Filtres2");
                        GenerePropertyChanged("SommeCircuit2");
                    }

                    if (test.CircuitNumber==3)
                    {
                        GenerePropertyChanged("Filtres3");
                        GenerePropertyChanged("SommeCircuit3");
                    }
                    }
                    break;
            }
        }


Quand je pose des point d’arrêt sur Fixture_PropertyChanged, je me rends compte que rien ne se déclenche.....
J'ai essayé plein de truc et a un moment donné j'ai decidé de charger 2 usercontrols au demarrage de mon appli ainsi:
  private void ChooseSheetBtn_Click(object sender, RoutedEventArgs e)
        {
            interactif01.LoadBlock(interactif01.Zone01FlowDoc, 1, "DirectFd01"); //chargement usercontro1
            interactif01.LoadBlock2(interactif01.Zone01FlowDoc, 1, "DirectFd01");// chargement usercontro1
            GetFixtureData(dataGrid);// chargement fichier xls dans datagrid
           
        }


Et là tout fonctionnent a merveille Fixture_PropertyChanged se déclenche bien (quand je change la valeur du circuitName ou circuitNumber dans ma datagrid) et fait son boulot, malheureusement que sur les 2 usercontrols creé au demarrage.
Si l'utilisateur en rajoute Fixture_PropertyChanged se declenche il fait son boulot mais rien ne se passe sur les usercontrol creés en runtime par l'utilsateur(aucun update)

En revanche si je charge 2 usercontroles au demarrage de l'application ainsi:
 private void ChooseSheetBtn_Click(object sender, RoutedEventArgs e)
        {
            
            GetFixtureData(dataGrid);// chargement fichier xls dans datagrid
            interactif01.LoadBlock(interactif01.Zone01FlowDoc, 1, "DirectFd01"); //chargement usercontro1
            interactif01.LoadBlock2(interactif01.Zone01FlowDoc, 1, "DirectFd01");// chargement usercontro1
          
        }


Fixture_PropertyChanged ne se declenche pas.....
Je précise également que les usercontrols créé par l'utilisateur se remplissent bien avec les bonnes données....
C'est a dire que quand je change la sélection de ma combox qui est dans le usercontrol je récupère bien les bonnes valeurs dans toute mes textboxs.
Je ne comprends pas.
Merci d'avance pour votre aide .
Bonne journée à bientot.

8 réponses

Messages postés
14922
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
26 octobre 2020
447
Salut,

Tu peux poster le code de LoadBlock, LoadBlock2 et GetFixtureData?
Messages postés
42
Date d'inscription
mardi 11 décembre 2018
Statut
Membre
Dernière intervention
28 juillet 2020

Re_salut Whismeril , je viens de me rendre compte que je n'avais pas commenter ta réponse .......
(juste répondu a ma question).
Salut bonne soirée.
Messages postés
14922
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
26 octobre 2020
447 >
Messages postés
42
Date d'inscription
mardi 11 décembre 2018
Statut
Membre
Dernière intervention
28 juillet 2020

En fait répondre c'est mieux, car les commentaires ça met vite la garouille dans le fil....
Messages postés
42
Date d'inscription
mardi 11 décembre 2018
Statut
Membre
Dernière intervention
28 juillet 2020

Salut Whismeril, toujours toi a répondre à mes problèmes.Merci.
Bon depuis mon post j' ai changer quelques truc dans mon code....
Dans la MainWindow:

private void ChooseSheetBtn_Click(object sender, RoutedEventArgs e)
        {
            GetFixtureData();// chargement fichier xls dans datagrid
         }


 public void GetFixtureData()
        {
            Class.ExcelDataService _objExcelSer;
            _objExcelSer = new Class.ExcelDataService();
            try
            {
                ListFixture.Add(_objExcelSer.ReadRecordFromEXCELAsync().Result);
                lightDataGrid.ItemsSource = ListFixture;

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }


la class ExcelDataService:

 public class ExcelDataService
    {


        MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
        OleDbConnection Conn;
        OleDbCommand Cmd;

        public ExcelDataService()
        {
            string ExcelFilePath = mainWindow.WygFileDirectory.Text;
            string excelConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ExcelFilePath + ";Extended Properties=Excel 12.0;Persist Security Info=True";
            Conn = new OleDbConnection(excelConnectionString);
        }
        /// <summary>  
        /// Method to Get All the Records from Excel  
        /// </summary>  
        /// <returns></returns>   
        public async Task<ObservableCollection<Fixture>> ReadRecordFromEXCELAsync()
        {
            ObservableCollection<Fixture> ListFixture = new ObservableCollection<Fixture>();
            char[] MyChar = { 'W', ' ' };
            await Conn.OpenAsync();
            Cmd = new OleDbCommand();
            Cmd.Connection = Conn;
            Cmd.CommandText = "Select * from [" + mainWindow.MySheetName.Text + "$]";
            var Reader = await Cmd.ExecuteReaderAsync();
            if (Reader.HasRows == true)
            {
                while (Reader.Read())
                {
                   ListFixture.Add(new Fixture()
                    {
                        Spot =ConvertionHelper.Converter.ConvertToInt(Reader["Spot"].ToString()),
                        CircuitName = Reader["Circuit Name"].ToString(),
                        CircuitNumber = ConvertionHelper.Converter.ConvertToInt(Reader["Circuit Number"].ToString()),
                       
                        Type = Reader["Type"].ToString(),
                        Manufacturer = Reader["Manufacturer"].ToString(),
                        Wattage = ConvertionHelper.Converter.ConvertToInt(Reader["Wattage"].ToString().TrimEnd(MyChar)),
                        Weight = ConvertionHelper.Converter.ConvertToDecimal(Reader["Weight"].ToString().Replace(".", ",")),
                        Mode = Reader["Mode"].ToString(),
                    });
                }
                //MainWindow.ListFixture = new ObservableCollection<Fixture>(MainWindow.ListFixture.OrderBy(i => i.Spot));
            }

            Reader.Close();
            Conn.Close();
            return ListFixture;


        }

    }


Dans un usercontrol juste un ensemble de control avec des boutons/flowdoc/ControlTab:
le loadBlock 1 et 2 sont identiques juste le blockdirect.Circuit1Cbx.SelectedIndex = 1
dans le loadblock2 (c’était juste pour essayer de charger 2 blockdirect avec des données différentes.

 public void LoadBlock(FlowDocument _Fd, int num, string Directname)
        {
            BlockDirect blockdirect = new BlockDirect();
            blockdirect.Circuit1Cbx.SelectedIndex = 0;
            blockdirect.Margin = new Thickness(10);
            MainWindow.ListBlock.Add(blockdirect);
            BlockUIContainer blockUIContainer = new BlockUIContainer();
            blockdirect.Direct.Name = Directname;
            blockUIContainer.Name = "blockuicontainer" + num;
            blockUIContainer.Child = blockdirect;
            _Fd.Blocks.Add(blockUIContainer);
            //ObservableCollection<Fixture> listprovisoire = new ObservableCollection<Fixture>();
            //listprovisoire.Add(MainWindow.ListFixture);
            //MainWindow.ListFixture.Clear();                   ///!!!!!!Avec ces lignes decommentées sa fonctionne......Une rustine!!!!!
            //MainWindow.ListFixture.Add(listprovisoire);
        }


le bouton d'ajout d'un blockdirect:
private void AdddirectBtn_Click(object sender, RoutedEventArgs e)
        {
            switch (BlockTabControl.SelectedIndex)
            {
                case 0:
                    LoadBlock(Zone01FlowDoc, 1, "DirectFd01");
                    break;
                case 1:
                    LoadBlock(Zone02FlowDoc, 2, "DirectFd02");
                    break;
                case 2:
                    LoadBlock(Zone03FlowDoc, 3, "DirectFd03");
                    break;
                case 3:
                    LoadBlock(Zone04FlowDoc, 4, "DirectFd04");
                    break;
                case 4:
                    LoadBlock(Zone05FlowDoc, 5, "DirectFd05");
                    break;
                case 5:
                    LoadBlock(Zone06FlowDoc, 6, "DirectFd06");
                    break;

            }
}


Ce matin après mon premier post j'ai rajouter les lignes commentées à la fin de Loadblock et ça fonctionne....
Mais bon c'est pas une solution....

Je me demande si la coquille vient pas du fait que
l'observable collection ListFixture est statique (je voulais avoir accès à elle de partout.....).
 public MainWindow()
        {
            InitializeComponent();
            ListFixture = new ObservableCollection<Fixture>();
            DataContext = this;
        }

        public static ObservableCollection<Fixture> ListFixture { get; set; }


Voila Voila.
encore merci pour le temps passé à me lire.
A très bientôt.
Messages postés
14922
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
26 octobre 2020
447
toujours toi a répondre à mes problèmes

en fait nous sommes très peu à répondre régulièrement et depuis de longs mois, je suis le seul en WPF.
Et pourtant, je suis encore loin de maitriser le XAML.

le loadBlock 1 et 2 sont identiques juste le blockdirect.Circuit1Cbx.SelectedIndex = 1
2 codes quasiment identiques, c'est une erreur. S'il y a un bug, il faut que tu le corriges 2 fois. Si le fonctionnement change, il faut que tu modifies 2 fois.
Un bon code est le plus factorisé possible => tu écris un code unique qui gère les 2 différences grâce, par exemple à un paramètre.

Il va me falloir un peu de temps pour analyser tout ça
Messages postés
14922
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
26 octobre 2020
447
Je ne sais pas si c'est du au fait que la collection soit statique, mais au cas où

à la place de
        MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
        public BlockDirect()
        {
            InitializeComponent();
            //....



        MainWindow mainWindow;
        public BlockDirect(MainWindow FenetrePrincipale)
        {
            InitializeComponent();
            mainWindow = FenetrePrincipale;
            //....


Et à la place de
BlockDirect blockdirect = new BlockDirect();


BlockDirect blockdirect = new BlockDirect(this);


Et là tu amènes correctement la référence à ta fenêtre dans tes différents contrôles, et la collection n'a plus à être une propriété statique.

Cela dit, tu pourrais (devrais) aussi renseigner la propriété Parent
Messages postés
42
Date d'inscription
mardi 11 décembre 2018
Statut
Membre
Dernière intervention
28 juillet 2020

Mon bon whismeril,
Merci pour tes réponses j'ai essayé tes solutions malheureusement ça ne change rien a mon problème ..

Je pense que mon application n' est pas vraiment codé dans les régles de l'art, dans le sens ou je n'ai pas encore assimilé toutes les subtilités lié à la programmation...
c'est pas faute de lire des bouquins , et de trainer sur différent forum....
Je vais dés demain me renseigner plus amplement sur la propriété Parent.

Pour le loadblock2 c’était juste un copier coller vite fait pour voir si quand je chargeais 2 usercontrols avec des données différentes ces 2 derniers prenaient en compte le Fixture_PropertyChanged.(ce qu'ils font).

Encore une fois merci à toi d'avoir pris sur ton temps personnel pour me lire et me répondre.

Maintenant j'ai une question un peu plus personnel .
Voila mon travail est au point mort avec le covid et c'est pas prés de reprendre....
J'ai 2000€ sur qui traine sur mon compte Cpf (compte professionnel formation).
Avec ça je vais pas aller bien loin mais, mais j'ai bien envie de les éclater....
Et me payer 1 semaine de formation Wpf/MvvM (m2iFormation a Rennes)
J'ai peur de pas avoir le niveau ....
Et avec pole emploi, mon age, j'aurais jamais une formation de plusieurs mois pour reprendre tout depuis le début...
Qu'est ce que t'en pense je l'a fait ou pas?

Bonne Fin de soirée a toi.
Encore Merci.
Messages postés
14922
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
26 octobre 2020
447
Je ne suis pas en mesure de répondre à ton questionnement sur cette formation tout de suite.
Et de prime abord ça s’éloigne de la question initiale et donc mériterait un sujet dédié.

Cela dit le pattern Mvvm (que j’ai personnellement assez de mal à bien appliquer [un seul projet avec un vrai codeur pour le moment]) est loin de ce que tu codes à ce jour.

Une étape intermédiaire pourrait être le MVC et le MVC pourrait aussi solutionner ton problème.

Par contre je n’ai pas le temps d’entrer dans les détails ces jours ci.
Je te propose la lecture d’une série de tutoriels que j’ai rédigé, ils reflètent les tâtonnements d’un autodidacte et seront, je l’espère un début de réponse à ton problème technique et ton questionnement concernant la formation https://codes-sources.commentcamarche.net/faq/11239-la-programmation-objet-appliquee-a-net-par-l-exemple-partie-1-sur-3
Messages postés
14922
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
26 octobre 2020
447
Messages postés
2248
Date d'inscription
samedi 11 janvier 2014
Statut
Contributeur
Dernière intervention
24 octobre 2020
115
Bonsoir
Une optimisation du code
public void Fixture_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
        int chiffre;
        Fixture test = sender as Fixture;
        switch (e.PropertyName)
        { 
              case "CircuitNumber" : // pour avoir int chiffre 
                    chiffre = test.CircuitNumber;
                    break;
             case "CircuitName": // pour avoir int chiffre 
                    chiffre = test.CircuitName;
                    break;
        }
        if (chiffre > 0 & chiffre < 4) // int chiffre va de 1 jusqu'à 3 dans les 2 choix
        {
             GenerePropertyChanged("Filtres" + chiffre.ToString());
             GenerePropertyChanged("SommeCircuit" + chiffre.ToString());
         }
}


Messages postés
14922
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
26 octobre 2020
447
Pour ton problème, tu pourrais peut-être utiliser une BindingList, l'événement ListChanged s'active aussi bien quand la collection est modifiée (ajout d'item, suppression , etc) que lorsqu'un item est modifié