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

C# Discussion :

WPF - Actualisation écran (Multithread)


Sujet :

C#

  1. #1
    Membre confirmé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2017
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2017
    Messages : 71
    Par défaut WPF - Actualisation écran (Multithread)
    Bonjour

    J'ai mon application WPF qui travaille avec un second Thread. Ce thread va dans SQL chercher des données dans une table, me les stock dans une datatable, ensuite je remplis une ObservableCollection avec ma classe dans une boucle puis à la fin de la boucle je donne la source au Binding pour l'affichage dans le XAML :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Application.Current.Dispatcher.Invoke(new Action(() => this.DataContext = lstOperations));
    Sauf qu'au début de la fonction avant de récupérer mes données SQL je suis obligé de nettoyer cette liste pour pas que ça concatène 2 fois les données :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Application.Current.Dispatcher.Invoke(new Action(() => lstOperations.Clear()));
    Mon problème est le suivant : l'écran se vide, travaille, puis recharge les données

    Quelle serait la façon de faire qui permettrait de ne pas voir l'écran se vider et que le tout soit remplacé une fois le traitement terminé ?

    Par avance, merci.

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 193
    Par défaut
    ton chargement doit se faire dans autre chose que lstoperations
    une fois ce chargement terminé, tu fais invoke lstoperations.clear + lstoperations = listetemporaire + set datacontext
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre confirmé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2017
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2017
    Messages : 71
    Par défaut
    Salut
    C'est bien ce à quoi j'avais pensé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Application.Current.Dispatcher.Invoke(new Action(() => lstOperationsTemp.Clear())); // Je vide ma liste temp
     
    for(int i = 0; i < dvOp.Count; i++)
    {
            Application.Current.Dispatcher.Invoke(new Action(() => lstOperationsTemp.Add(clOp))); // J'ajoute mes enregistrements dans ma liste Temp
    }
     
                Application.Current.Dispatcher.Invoke(new Action(() => lstOperations.Clear()));  // Je vide la liste d'affichage
                lstOperations = lstOperationsTemp; // Je remplis la liste d'affichage avec la Temp précédemment rempli
                Application.Current.Dispatcher.Invoke(new Action(() => this.DataContext = lstOperations)); // Je set le DataContext avec ma liste d'affichage
    Le problème avec cette méthode, on dirait qu'il se souvient du lstOperations = lstOperationsTemp, quand je clear la lstOperationsTemp (première ligne de mon code) on dirait qu'i l me vide aussi ma liste d'affichage. Conclusion à la fin de ma fonction : mon écran est tout vide. Je vois la liste appraître, puis disparaite.

    Merci

  4. #4
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    940
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 940
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lstOperations = lstOperationsTemp;
    Quand tu fais ça la liste référencée par lstOperations est celle référencée par lstOperationsTemp, ce n'est pas une copie ; donc si à un moment tu vides lstOperationsTemp ça vide aussi lstOperations. Pour éviter cela, soit tu crées une nouvelle liste à affecter à lstOperations (et dans ce cas ce n'est même pas la peine de la vider) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lstOperations = new List(lstOperationsTemp);
    soit tu ajoutes le contenu de la liste temporaire à la liste permanente, après l'avoir vidée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    lstOperations.Clear();
    lstOperations.AddRange(lstOperationsTemp);
    La méthode List.AddRange() permet d'ajouter directement dans la liste tous les items d'un conteneur, sans avoir à faire de boucle, ce qui peut s'avérer plus performant.

  5. #5
    Membre confirmé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2017
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2017
    Messages : 71
    Par défaut
    Salut

    Merci pour ta réponse

    2 problèmes : avec ta solution 1 alors je créé ma liste dans ma fonction et du coup je ne peux plus l'appeler dans l'autre fonction

    Avec la solution 2, ma liste étant une ObservableCollection, AddRange n'est pas une propriété possible. Comment l'ajouter ?

    EDIT : J'ai réussi, je parcours la liste Temp qui elle est gloable dans ma 2ème fonction. Merci

  6. #6
    Membre confirmé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2017
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2017
    Messages : 71
    Par défaut
    Bonjour

    J'ai un peu changé ma méthode de faire :

    J'ai cette déclaration en globale :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    private ObservableCollection<CL_Operation> _lstOperationsTemp = new ObservableCollection<CL_Operation>();
            public ObservableCollection<CL_Operation> LstOperationsTemp
            {
                get { return _lstOperationsTemp; }
                set
                {
                    _lstOperationsTemp = value;
                }
            }
    Et ceci en démarrage de l'application :

    Du coup, j'ai à nouveau le même problème, l'écran se vide, travaille, puis recharge les données

    Cela doit venir du fait que désormais c'est this en DataContext.

    La solution alternative que j'ai trouvé c'est de ne pas définir le DataContext = this au chargement de la fenêtre

    Je le mets à "Null" au début de ma fonction et je le réassigne à "this" à la fin de la fonction. Résultat : l'écran est noir et ré-affiche directement toute la liste d'un seul coup. Plus il y a de données plus l'écran est noir longtemps bien sûr

    Comment pourrais-je procéder pour éviter cet écran noir ?

    Merci

    Avez-vous une idée ?

    Merci.

  7. #7
    Membre Expert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 056
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    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 056
    Par défaut
    Il n'y a pas d'intérêt à faire un clear de ta collection pour la re-remplir élément par élément parce que ta collection va générer x évènements de modification qui vont probablement se traduire par un mini-freeze de l'application.

    Il te suffit de travailler sur une collection temporaire (déclarer au niveau de ta fonction), tu fais ce que tu as à faire (transformation du dataset), et à la fin tu affectes la collection temporaire à ta propriété qui est utilisé par le binding.
    Bien sur il faut que dans le set de ta propriété tu fasses bien un appelle de notifyPropertyChanged.

  8. #8
    Membre confirmé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2017
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2017
    Messages : 71
    Par défaut
    Salut

    Merci pour ta réponse.

    J'ai essayé et pourtant ça ne fonctionne pas, ma liste reste vide.

    J'ai essayé de pleins de manières différentes et impossible

    As-tu un exemple ?

    Comment faire le notifypropertychanged au set ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    private ObservableCollection<CL_Operation> _lstOperationsTemp = new ObservableCollection<CL_Operation>();
            public ObservableCollection<CL_Operation> LstOperationsTemp
            {
                get { return _lstOperationsTemp; }
                set
                {
                    _lstOperationsTemp = value;
                }
            }
    Merci

  9. #9
    Membre Expert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 056
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    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 056
    Par défaut
    Ce n'est pas ta liste temporaire qui doit faire appel à notifyPropertyChanged, elle ne devrait même pas être sous forme de propriété mais plutot dans une variable privé au sein de ta méthode.

    Pour l'appel de notifyPropertyChanged ca dépend de comment ta classe implémente INotifyPropertyChanged.
    Peux tu mettre le code en entier que tu utilises? Xaml et C#.

  10. #10
    Membre confirmé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2017
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2017
    Messages : 71
    Par défaut
    Bonjour à tous. J'ai un petit problème : sur mon ordinateur, j'ai aucun problème, le refresh se fait automatiquement sans rien y voir. Par contre sur un autre PC j'ai quand même un "petit flash" au moment du refresh. Je ne comprends pas pourquoi : les 2 en Windows 10, x64, etc.
    Ce qui est encore plus étrange : sur mon PC à moi, ce problème apparaît quand même, mais une fois toutes les 5 ou 10 fois, et pour le même appel de données (même quantité de ligne et exactement même données SQL). Sur les autres PC c'est systématique.

    Si quelqu'un a une idée ? Je vais répondre à micka132 ce qui vous aidera peut-être à me dire POURQUOI j'ai ce problème.

    Merci micka132 pour ta réponse. Effectivement ma liste temp je l'avais mise plus en propriété mais en variable privé dans la méthode, cependant le problème persiste malheureusement.

    Voici le code xaml :

    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
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:Plutus" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="Plutus.MainWindow"
            Title="Plutus" Height="523.725" Width="898" WindowStartupLocation="CenterScreen" WindowState="Maximized" Loaded="Window_Loaded" Icon="PlutusIcone.ico">
        <Window.Resources>
            <Style TargetType="ScrollBar">
                <Setter Property="Width" Value="35"/>
            </Style>
        </Window.Resources>
        <Grid>
            <Grid.Background>
                <ImageBrush ImageSource="Images/FondPlutus.png" Stretch="UniformToFill" />
            </Grid.Background>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="0.03*" />
                <RowDefinition Height="0.05*" />
                <RowDefinition Height="0.05*" />
                <RowDefinition Height="0.87*"/>
                <RowDefinition Height="0.03*" />
            </Grid.RowDefinitions>
            <Rectangle Fill="White" Grid.Column="1" Grid.Row="0" />
            <Label Grid.Row="0" Grid.Column="1" Background="White" Content="LISTE" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" FontWeight="Bold"/>
            <Label Grid.Row="0" Grid.Column="0" Background="WHite" />
            <Image Source="Images/UNE.jpg" HorizontalAlignment="Left" Grid.Row="0" Grid.Column="0" />
            <Label Grid.Row="0" Grid.Column="3" Background="WHite" />
            <Image Source="Images/_H.jpg" HorizontalAlignment="Right" Grid.Row="0" Grid.Column="2" />
            <!--<Button Visibility="{Binding strShowMenu}" Name="btnParamsAffichage" Content="Paramètres" HorizontalAlignment="Left" Width="100" Grid.Column="0" Grid.Row="1" Background="#b2c9ef" Click="btnParamsAffichage_Click"  />-->
            <!--<Button Visibility="{Binding strShowMenu}" Name="btnAttribution" Content="Attribution" HorizontalAlignment="Right" Width="100" Grid.Column="1" Grid.Row="1" Background="#b2c9ef" Click="btnAttribution_Click"  />-->
            <Image Visibility="{Binding strShowMenu}"  Name="btnParamsAffichage" HorizontalAlignment="Left" Width="100" Grid.Column="0" Grid.Row="2" MouseLeftButtonUp="btnParamsAffichage_Click">
                <Image.Style>
                    <Style TargetType="{x:Type Image}">
                        <Setter Property="Source" Value="Images/ParametresAffichage.png"/>
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Source" Value="Images/ParametresAffichageHover.png"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Image.Style>
            </Image>
            <Label FontSize="28" FontWeight="Bold" Grid.Row="2" Content="{Binding strFiltres}" Foreground="White" Margin="100,0, 0,0" VerticalAlignment="Center" />
            <Image Name="btnAttribution" HorizontalAlignment="Right" Width="100" Grid.Column="2" Grid.Row="2" MouseLeftButtonUp="btnAttribution_Click">
                <Image.Style>
                    <Style TargetType="{x:Type Image}">
                        <Setter Property="Source" Value="Images/BarCode.png"/>
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Source" Value="Images/BarCodeHover.png"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Image.Style>
            </Image>
            <Label FontSize="28" FontWeight="Bold" Foreground="White" Content="{Binding strSelection}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" />
            <ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="3" Grid.ColumnSpan="3">
                <ItemsControl VerticalAlignment="Top" x:Name="lvDataBinding" HorizontalContentAlignment="Stretch" BorderThickness="0" Margin="10" Grid.Row="3" Background="{x:Null}" ItemsSource="{Binding LstOperations}" Foreground="White">
                <ItemsControl.ItemTemplate>
                    <!--<DataTemplate DataType="{x:Type local:CL_Operation}">-->
                        <DataTemplate>
                            <Border BorderBrush="White" BorderThickness="1" CornerRadius="3" Margin="0,3" Grid.ColumnSpan="0" Background="Transparent" HorizontalAlignment="Left" VerticalAlignment="Top">
                            <Grid Width="{Binding strWidth}" Height="60" Background="Transparent" Margin="0,1">
                                <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="0.05*" />
                                        <ColumnDefinition Width="0.09*" />
                                        <ColumnDefinition Width="0.1*" />
                                        <ColumnDefinition Width="0.12*" />
                                        <ColumnDefinition Width="0.1*" />
                                        <ColumnDefinition Width="0.1*" />
                                        <ColumnDefinition Width="0.1*" />
                                        <ColumnDefinition Width="0.04*" />
                                        <ColumnDefinition Width="0.04*" />
                                        <ColumnDefinition Width="0.04*" />
                                        <ColumnDefinition Width="0.04*" />
                                        <ColumnDefinition Width="0.06*" />
                                    </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition />
                                    <RowDefinition />
                                    <RowDefinition />
                                    <RowDefinition />
                                     <RowDefinition />
                                     <RowDefinition />
                                    </Grid.RowDefinitions>
                                    <UniformGrid Tag="{Binding strRueck}" Background="{Binding scbBackColor}" Grid.Column="0" Grid.Row="0" Grid.RowSpan="4" MouseLeftButtonUp="ClickRowOf" >
                                        <UniformGrid.Style>
                                            <Style TargetType="{x:Type UniformGrid}">
                                                <Style.Triggers>
                                                    <Trigger Property="IsMouseOver" Value="False">
                                                        <Setter Property="Opacity" Value="1"></Setter>
                                                    </Trigger>
                                                    <Trigger Property="IsMouseOver" Value="True">
                                                        <Setter Property="Opacity" Value="0.8"></Setter>
                                                    </Trigger>
                                                </Style.Triggers>
                                            </Style>
                                        </UniformGrid.Style>
                                        <TextBlock Text="{Binding strPriorite}" FontSize="36" Foreground="Red" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold"/>
                                    </UniformGrid>
                                    <UniformGrid  Grid.Column="0" Grid.Row="4" Grid.RowSpan="2" Background="{Binding scbBackColor}">
                                        <TextBlock Text="{Binding strSsSect}" FontSize="14" Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Bottom" FontWeight="Bold" />
                                    </UniformGrid>
                                    <UniformGrid  Grid.Column="1" Grid.Row="0" Grid.RowSpan="6">
                                    <TextBlock Text="{Binding strRetardAvanceText}" FontSize="28" Foreground="{Binding scbColorRetardAvance}" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" />
                                </UniformGrid>
                                <UniformGrid  Grid.Column="2" Grid.Row="0" Grid.ColumnSpan="2" Grid.RowSpan="4">
                                    <UniformGrid.Style>
                                        <Style TargetType="{x:Type UniformGrid}">
                                            <Style.Triggers>
                                                <Trigger Property="IsMouseOver" Value="true">
                                                    <Setter Property="Background" Value="Gray"/>
                                                </Trigger>
                                            </Style.Triggers>
                                        </Style>
                                    </UniformGrid.Style>
                                        <TextBlock Tag="{Binding strRueck}" Foreground="{Binding scbColorNumOfOp}" Text="{Binding strNoOfOp}" FontSize="26" FontWeight="Bold" MouseLeftButtonUp="ClickNoOfOp"/>
                                </UniformGrid>
                                <UniformGrid  Grid.Column="2" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="3">
                                    <TextBlock Text="{Binding strDescriptionOp}" FontSize="14" Foreground="White"/>
                                </UniformGrid>
                                <UniformGrid Grid.Column="4" Grid.Row="0" Grid.RowSpan="2">
                                    <TextBlock Text="{Binding strNoArticle}" FontSize="14" Foreground="White" FontWeight="Bold"/>
                                </UniformGrid>
                                <UniformGrid  Grid.Column="4" Grid.Row="2" Grid.RowSpan="2">
                                    <TextBlock Text="{Binding strDateFormatee}" FontSize="14" Foreground="White" FontWeight="Bold"/>
                                </UniformGrid>
                                <UniformGrid Grid.Column="5" Grid.Row="0" Grid.RowSpan="2">
                                    <TextBlock Text="{Binding strPcesPoste}" FontSize="14" Foreground="White"/>
                                </UniformGrid>
                                <UniformGrid  Grid.Column="5" Grid.Row="2" Grid.RowSpan="2">
                                    <TextBlock Text="{Binding strTpsPoste}" FontSize="14" Foreground="White"/>
                                </UniformGrid>
                                <UniformGrid  Grid.Column="6" Grid.Row="0" Grid.RowSpan="2">
                                    <TextBlock Text="{Binding strTempsPoste}" FontSize="14" Foreground="White"/>
                                </UniformGrid>
                                <UniformGrid  Grid.Column="6" Grid.Row="2" Grid.RowSpan="2">
                                    <TextBlock Text="{Binding strClient}" FontSize="14" Foreground="White"/>
                                </UniformGrid>
                                <UniformGrid  Grid.Column="5" Grid.Row="4" Grid.RowSpan="2" Grid.ColumnSpan="3">
                                    <TextBlock Text="{Binding strTypeOp}" FontSize="14" Foreground="White"/>
                                </UniformGrid>
                                <UniformGrid  Grid.Column="9" Grid.Row="4" Grid.RowSpan="2">
                                    <TextBlock Text="{Binding strAuart}" FontSize="12" Foreground="White" FontWeight="Bold"/>
                                </UniformGrid>
                                <UniformGrid  Grid.Column="7" Grid.Row="0" Grid.RowSpan="4">
                                        <Image ToolTip="{Binding strDesBlocage}" Source="{Binding strImageToDisplay}" Visibility="{Binding strWorkingVisibility}">
                                            <Image.Style>
                                                <Style TargetType="Image">
                                                    <Style.Triggers>
                                                        <Trigger Property ="IsMouseOver" Value="True">
                                                        </Trigger>
                                                    </Style.Triggers>
                                                </Style>
                                                </Image.Style>
                                        </Image>
                                    </UniformGrid>
                                    <UniformGrid  Grid.Column="8" Grid.Row="0" Grid.RowSpan="4" >
                                        <Image Tag="{Binding strRueck}" ToolTip="{Binding strEmpAssigned}" Visibility="{Binding strAttributionVisibility}" MouseLeftButtonUp="ClickAttribution">
                                            <Image.Style>
                                                <Style TargetType="{x:Type Image}">
                                                    <Setter Property="Source" Value="Images/Attribution.png"/>
                                                    <Style.Triggers>
                                                        <Trigger Property="IsMouseOver" Value="True">
                                                            <Setter Property="Source" Value="Images/AttributionHover.png"/>
                                                        </Trigger>
                                                    </Style.Triggers>
                                                </Style>
                                            </Image.Style>
                                        </Image>
                                    </UniformGrid>
                                    <UniformGrid  Grid.Column="9" Grid.Row="0" Grid.RowSpan="4" >
                                        <Image Tag="{Binding strRueck}" ToolTip="{Binding strPostePrevCount}" Visibility="{Binding strRegroupementVisibility}" MouseLeftButtonUp="ClickRegroupement">
                                            <Image.Style>
                                                <Style TargetType="{x:Type Image}">
                                                    <Setter Property="Source" Value="Images/Regroupement.png"/>
                                                    <Style.Triggers>
                                                        <Trigger Property="IsMouseOver" Value="True">
                                                            <Setter Property="Source" Value="Images/Regroupement.png"/>
                                                        </Trigger>
                                                    </Style.Triggers>
                                                </Style>
                                            </Image.Style>
                                        </Image>
                                    </UniformGrid>
                                    <UniformGrid Tag="{Binding strRueck}" Grid.Column="11" Grid.Row="0" Grid.RowSpan="3" HorizontalAlignment="Left" MouseLeftButtonUp="OpenPlan">
                                        <Image Source="Images/Plan.png" Visibility="Visible" />
                                        <UniformGrid.Style>
                                            <Style TargetType="{x:Type UniformGrid}">
                                                <Style.Triggers>
                                                    <Trigger Property="IsMouseOver" Value="true">
                                                        <Setter Property="Background" Value="Gray"/>
                                                    </Trigger>
                                                    <Trigger Property="IsMouseOver" Value="false">
                                                        <Setter Property="Background" Value="Transparent"/>
                                                    </Trigger>
                                                </Style.Triggers>
                                            </Style>
                                        </UniformGrid.Style>
                                    </UniformGrid>
                                       <UniformGrid Tag="{Binding strRueck}" Grid.Column="11" Grid.Row="3" Grid.RowSpan="3" HorizontalAlignment="Left" MouseLeftButtonUp="OpenIT">
                                        <Image Source="Images/IT.png" Visibility="Visible" />
                                        <UniformGrid.Style>
                                            <Style TargetType="{x:Type UniformGrid}">
                                                <Style.Triggers>
                                                    <Trigger Property="IsMouseOver" Value="true">
                                                        <Setter Property="Background" Value="Gray"/>
                                                    </Trigger>
                                                    <Trigger Property="IsMouseOver" Value="false">
                                                        <Setter Property="Background" Value="Transparent"/>
                                                    </Trigger>
                                                </Style.Triggers>
                                            </Style>
                                        </UniformGrid.Style>
                                    </UniformGrid>
                                </Grid>                            
                        </Border>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <UniformGrid Columns="2"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </ScrollViewer>
            <Label HorizontalAlignment="Right" FontSize="14" Foreground="White" Grid.Row="4" Grid.Column="2" Content="{Binding strTotaux}"></Label>
        </Grid>
    </Window>
    Mon code C#

    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
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
          public partial class MainWindow : Window, INotifyPropertyChanged
        {
            #region Évenement qui permet de déclencher l'événement INotifyPropertyChanged et mettre à jour le binding
            public void Set<TValue>(ref TValue field, TValue newValue, [CallerMemberName] string propertyName = "")
            {
                if (EqualityComparer<TValue>.Default.Equals(field, default(TValue)) || !field.Equals(newValue))
                {
                    field = newValue;
     
                    if (PropertyChanged != null)
                        PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
                }
            }
     
            public event PropertyChangedEventHandler PropertyChanged;
            #endregion
     
            public static RangeObservableCollection<CL_Operation> _lstOperations = new RangeObservableCollection<CL_Operation>();
            public static RangeObservableCollection<CL_Operation> LstOperations
            {
                get { return _lstOperations; }
                set { _lstOperations = value; }
            }
     
            private string _strTotaux;
            public string strTotaux
            {
                get { return _strTotaux; }
                set { Set(ref _strTotaux, value); }
            }
     
            private string _strShowMenu;
            public string strShowMenu
            {
                get { return _strShowMenu; }
                set { Set(ref _strShowMenu, value); }
            }
     
            private string _strSelection;
            public string strSelection
            {
                get { return _strSelection; }
                set { Set(ref _strSelection, value); }
            }
     
            private string _strFiltres;
            public string strFiltres
            {
                get { return _strFiltres; }
                set { Set(ref _strFiltres, value); }
            }
     
    public MainWindow()
            {
                InitializeComponent();
     
                DataContext = this;
            }
     
      public void GetList()
            {
                strShowMenu = "Hidden";
     
                RangeObservableCollection<CL_Operation> _lstOperationsTemp = new RangeObservableCollection<CL_Operation>();
     
                strSelection = "";
     
                foreach (var item in Var.lstSelectedLignesChoisi)
                {
                    strSelection += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedIlotsChoisi)
                {
                    strSelection += " " + item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedPostesTravailChoisi)
                {
                    strSelection += " " + item.ToString() + " ";
                }
     
                strFiltres = "";
     
                foreach (var item in Var.lstSelectedOperations)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedTypesDiamant)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedClient)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedMatricule)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedTypeOrdre)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedPriorites)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                if (!string.IsNullOrEmpty(Var.strFiltreNoOF))
                    strFiltres += Var.strFiltreNoOF;
     
                if (!string.IsNullOrEmpty(Var.strFiltreArticle))
                    strFiltres += Var.strFiltreArticle;
     
                if (!string.IsNullOrEmpty(Var.strFiltreComposant))
                    strFiltres += Var.strFiltreComposant;
     
                if (!string.IsNullOrEmpty(Var.strFiltreAgentOrdo))
                    strFiltres += Var.strFiltreAgentOrdo;
     
                if (!string.IsNullOrEmpty(Var.strFiltreGestMRP))
                    strFiltres += Var.strFiltreGestMRP;
     
                if (!string.IsNullOrEmpty(Var.strFiltreSquelette) && Var.strFiltreSquelette != "TOUS")
                    strFiltres += Var.strFiltreSquelette + " SQUELETTE";
     
                strWhere = "";
                strWhere = Where(Var.lstSelectedLignesChoisi, Var.lstSelectedIlotsChoisi, Var.lstSelectedPostesTravailChoisi, Var.lstSelectedOperations, Var.lstSelectedTypesDiamant, Var.lstSelectedClient, Var.lstSelectedMatricule, Var.lstSelectedTypeOrdre, Var.strFiltreArticle, Var.strFiltreNoOF, Var.strFiltreComposant, Var.strFiltreAgentOrdo, Var.strFiltreGestMRP, Var.lstSelectedPriorites, Var.strFiltreSquelette);
                CreateOrderBy();
     
                dvOps = dtOps.DefaultView;
     
                Application.Current.Dispatcher.Invoke(new Action(() => _lstOperationsTemp.Clear()));
                dtOps.Clear();
     
                string strQueryDatas;
     
                SqlConnection con = new SqlConnection(connectionString);
     
                strQueryDatas = "SELECT * FROM [DB].[dbo].[View_] " + strWhere + " " + strOrderBy;
     
                SqlDataAdapter adOps = new SqlDataAdapter(strQueryDatas, con);
     
                adOps.Dispose();
     
                try
                {
                    con.Open();
                    SqlCommand sqlCmd = new SqlCommand(strQueryDatas, con);
                    sqlCmd.CommandTimeout = 500;
                    adOps.SelectCommand = sqlCmd;
                    adOps.Fill(dtOps);
                    adOps.Dispose();
                    sqlCmd.Dispose();
                    con.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
     
                DateTime dtNow = DateTime.Now;
     
                double dblTotalQte = 0;
                double dblTotalOp = 0;
                double dblTotalTemps = 0;
                double dblTotalJoursRetard = 0;
     
                for (int i = 0; i < dvOps.Count; i++)
                {
                    clOp = new CL_Operation();
     
                    clOp.strWidth = Convert.ToString(Convert.ToInt32(System.Windows.SystemParameters.PrimaryScreenWidth) / 2);
     
                    if (dvOps[i]["OP_IsWorking"].ToString().Trim() != "")
                        clOp.bIsWorking = Convert.ToBoolean(dvOps[i]["OP_IsWorking"].ToString().Trim());
                    else
                        clOp.bIsWorking = false;
     
                    clOp.bAnoOp = Convert.ToBoolean(dvOps[i]["AnoOP"].ToString().Trim());
     
                    if (clOp.bIsWorking && clOp.bAnoOp)
                    {
                        clOp.strImageToDisplay = "Images/TravailAnomalie.png";
                        clOp.strWorkingVisibility = "Visible";
                    }
                    else if (clOp.bAnoOp)
                    {
                        clOp.strImageToDisplay = "Images/Anomalie.png";
                        clOp.strWorkingVisibility = "Visible";
                    }
                    else if (clOp.bIsWorking)
                    {
                        clOp.strImageToDisplay = "Images/Travail.png";
                        clOp.strWorkingVisibility = "Visible";
                    }
                    else
                    {
                        clOp.strImageToDisplay = "Images/Travail.png";
                        clOp.strWorkingVisibility = "Hidden";
                    }
     
                    if (dvOps[i]["OP_IsAssigned"].ToString().Trim() != "")
                        clOp.bIsAssigned = Convert.ToBoolean(dvOps[i]["OP_IsAssigned"].ToString().Trim());
                    else
                        clOp.bIsAssigned = false;
     
                    if (clOp.bIsAssigned)
                        clOp.strAttributionVisibility = "Visible";
                    else
                        clOp.strAttributionVisibility = "Hidden";
     
                    clOp.strDesBlocage = dvOps[i]["DesBlocage"].ToString().Trim();
     
                    if(!string.IsNullOrEmpty(dvOps[i]["MATRICULE"].ToString().Trim()))
                        clOp.strMatriculeAssigned = Convert.ToInt32(dvOps[i]["MATRICULE"]).ToString().Trim();
     
                    clOp.strNameAssigned = dvOps[i]["NAME"].ToString().Trim();
                    clOp.strFirstNameAssigned = dvOps[i]["FIRSTNAME"].ToString().Trim();
                    clOp.strEmpAssigned = dvOps[i]["NAME"].ToString().Trim() + " " + dvOps[i]["FIRSTNAME"].ToString().Trim();
                    clOp.strNoOf = dvOps[i]["NumOF"].ToString().Trim();
                    clOp.strNoOfOp = dvOps[i]["NumOF"].ToString().Trim() + " - " + dvOps[i]["NumOP"].ToString().Trim();
                    clOp.strAuart = dvOps[i]["AUART"].ToString().Trim();
                    clOp.strMaufnr = dvOps[i]["MAUFNR"].ToString().Trim();
                    clOp.strCodeLigne = dvOps[i]["CodeLigne"].ToString().Trim();
                    clOp.strRueck = dvOps[i]["RUECK"].ToString().Trim();
                    clOp.strDescriptionOp = dvOps[i]["DesOpe"].ToString().Trim();
                    clOp.strNoArticle = dvOps[i]["NumArt"].ToString().Trim();
                    clOp.strDateFormatee = dvOps[i]["DateFormatee"].ToString().Trim();
                    clOp.strPcesPoste = Convert.ToString(Convert.ToDouble(String.Format("{0:0}", dvOps[i]["QtePoste"].ToString().Trim()))) + " pces";
                    clOp.strTpsPoste = Convert.ToString(Convert.ToDouble(String.Format("{0:0.00}", dvOps[i]["TpsChargePoste"].ToString()))) + " Hrs";
                    clOp.strClient = dvOps[i]["NomClientCourt"].ToString().Trim();
                    clOp.strTypeOp = dvOps[i]["MAKTX"].ToString().Trim();
                    clOp.strPriorite = dvOps[i]["PriorOF"].ToString().Trim();
                    clOp.strSsSect = dvOps[i]["SsSect"].ToString().Trim();
                    clOp.strDateDerBadge = Convert.ToDateTime(dvOps[i]["DatDerBadg"]);
                    clOp.strWorkStart = dvOps[i]["DATETIMEDEBUT"].ToString().Trim();
                    clOp.strNumOp = dvOps[i]["NumOpSt"].ToString().Trim();
                    clOp.strIDRegroupement = dvOps[i]["USR02"].ToString().Trim();
                    clOp.strFlagPostePrev = dvOps[i]["FlagPostePrev"].ToString().Trim();
                    clOp.strNumArtPere = dvOps[i]["NumArtPere"].ToString().Trim();
                    clOp.strMAKTXPere = dvOps[i]["MAKTXPere"].ToString().Trim();
     
                    //int iCountRegr = 0;
     
                    if (!string.IsNullOrEmpty(clOp.strIDRegroupement))
                    {
                        //string strQueryDatas2;
     
                        //SqlConnection con2 = new SqlConnection(connectionString);
                        SqlConnection con3 = new SqlConnection(connectionString);
                        SqlConnection con4 = new SqlConnection(connectionString);
     
                        //strQueryDatas2 = "SELECT COUNT (*) FROM [db].[dbo].[view] WHERE USR02 = '" + clOp.strIDRegroupement + "'";
     
                        //try
                        //{
                        //    con2.Open();
                        //    SqlCommand sqlCmd = new SqlCommand(strQueryDatas2, con2);
                        //    iCountRegr = (Int32)sqlCmd.ExecuteScalar();
                        //    //sqlCmd.CommandTimeout = 500;
                        //    con2.Close();
                        //}
                        //catch (Exception ex)
                        //{
                        //    MessageBox.Show(ex.Message);
                        //}
     
                        string strQueryDatas3;
     
                        strQueryDatas3 = "SELECT COUNT (*) FROM [db].[dbo].[Table] WHERE FlagPostePrev = 'POSTE' AND USR02 = '" + clOp.strIDRegroupement + "'";
     
                        try
                        {
                            con3.Open();
                            SqlCommand sqlCmd = new SqlCommand(strQueryDatas3, con3);
                            clOp.iCountRegrPoste = (Int32)sqlCmd.ExecuteScalar();
                            //sqlCmd.CommandTimeout = 500;
                            con3.Close();
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                        }
     
                        string strQueryDatas4;
     
                        strQueryDatas4 = "SELECT COUNT (*) FROM [db].[dbo].[Table] WHERE FlagPostePrev = 'PREV' AND USR02 = '" + clOp.strIDRegroupement + "'";
     
                        try
                        {
                            con4.Open();
                            SqlCommand sqlCmd = new SqlCommand(strQueryDatas4, con4);
                            clOp.iCountRegrPrev = (Int32)sqlCmd.ExecuteScalar();
                            //sqlCmd.CommandTimeout = 500;
                            con4.Close();
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                        }
     
                        clOp.strPostePrevCount = "Poste : " + clOp.iCountRegrPoste.ToString() + " / Prév : " + clOp.iCountRegrPrev.ToString();
                    }
     
                    if (string.IsNullOrEmpty(clOp.strIDRegroupement))
                        clOp.strRegroupementVisibility = "Hidden";
                    else
                        clOp.strRegroupementVisibility = "Visible";
     
                    Application.Current.Dispatcher.Invoke(new Action(() => _lstOperationsTemp.Add(clOp)));
     
                    DateTime dtRetard = Convert.ToDateTime(clOp.strDateFormatee);
                    DateTime dtTempsPoste = Convert.ToDateTime(clOp.strDateDerBadge);
                    TimeSpan tRetard = dtNow.Date - dtRetard.Date;
     
                    if (dtTempsPoste.ToString() == "01.01.1900 00:00:00")
                        dtTempsPoste = dtNow;
     
                    TimeSpan tTempsPoste = dtNow - dtTempsPoste;
     
                    dblTotalQte += Convert.ToDouble(dvOps[i]["QtePoste"].ToString().Trim());
                    dblTotalTemps += Convert.ToDouble(dvOps[i]["TpsChargePoste"].ToString().Trim());
                    dblTotalOp++;
     
                    clOp.strRetardAvanceText = Convert.ToString(Math.Abs(Convert.ToDouble(tRetard.TotalDays))) + " jrs";
     
     
     
                    clOp.scbBackColor.Freeze();
                    clOp.scbColorRetardAvance.Freeze();
                }
     
                strTotaux = "Total retard : " + dblTotalJoursRetard.ToString() + " Jours     Nb OPs : " + dblTotalOp.ToString() + "     Qte totale : " + dblTotalQte.ToString() + " Pces     Temps total : " + dblTotalTemps + " Hrs";
     
                Application.Current.Dispatcher.Invoke(new Action(() => LstOperations.Clear()));
                Application.Current.Dispatcher.Invoke(new Action(() => LstOperations.AddRange(_lstOperationsTemp)));
     
                Var.lstSelectedOperations.Clear();
                Var.lstSelectedTypesDiamant.Clear();
                Var.lstSelectedClient.Clear();
                Var.lstSelectedMatricule.Clear();
                Var.lstSelectedTypeOrdre.Clear();
                Var.strFiltreNoOF = "";
                Var.strFiltreArticle = "";
                Var.strFiltreComposant = "";
                Var.strFiltreAgentOrdo = "";
                Var.strFiltreGestMRP = "";
                Var.strFiltreSquelette = "";
     
                strShowMenu = "Visible";
            }
     
    }
    Par avance, MERCI, beaucoup pour l'analyse et l'aide.

    Edit : je me suis rendu compte qu'en faisant ce bout de code :

    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
      strSelection = "";
     
                foreach (var item in Var.lstSelectedLignesChoisi)
                {
                    strSelection += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedIlotsChoisi)
                {
                    strSelection += " " + item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedPostesTravailChoisi)
                {
                    strSelection += " " + item.ToString() + " ";
                }
     
                strFiltres = "";
     
                foreach (var item in Var.lstSelectedOperations)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedTypesDiamant)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedClient)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedMatricule)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedTypeOrdre)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedPriorites)
                {
                    strFiltres += item.ToString() + " ";
                }
     
                if (!string.IsNullOrEmpty(Var.strFiltreNoOF))
                    strFiltres += Var.strFiltreNoOF;
     
                if (!string.IsNullOrEmpty(Var.strFiltreArticle))
                    strFiltres += Var.strFiltreArticle;
     
                if (!string.IsNullOrEmpty(Var.strFiltreComposant))
                    strFiltres += Var.strFiltreComposant;
     
                if (!string.IsNullOrEmpty(Var.strFiltreAgentOrdo))
                    strFiltres += Var.strFiltreAgentOrdo;
     
                if (!string.IsNullOrEmpty(Var.strFiltreGestMRP))
                    strFiltres += Var.strFiltreGestMRP;
     
                if (!string.IsNullOrEmpty(Var.strFiltreSquelette) && Var.strFiltreSquelette != "TOUS")
                    strFiltres += Var.strFiltreSquelette + " SQUELETTE";
    En fait je modifie mon binding à chaque coup, ce qui me pose peut-être mon problème.

    J'ai donc essayé :

    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
    string strFiltresTemp = "";
                string strSelectionTemp = "";
     
     
     
                foreach (var item in Var.lstSelectedLignesChoisi)
                {
                    strSelectionTemp += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedIlotsChoisi)
                {
                    strSelectionTemp += " " + item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedPostesTravailChoisi)
                {
                    strSelectionTemp += " " + item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedOperations)
                {
                    strFiltresTemp += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedTypesDiamant)
                {
                    strFiltresTemp += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedClient)
                {
                    strFiltresTemp += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedMatricule)
                {
                    strFiltresTemp += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedTypeOrdre)
                {
                    strFiltresTemp += item.ToString() + " ";
                }
     
                foreach (var item in Var.lstSelectedPriorites)
                {
                    strFiltresTemp += item.ToString() + " ";
                }
     
                if (!string.IsNullOrEmpty(Var.strFiltreNoOF))
                    strFiltresTemp += Var.strFiltreNoOF;
     
                if (!string.IsNullOrEmpty(Var.strFiltreArticle))
                    strFiltresTemp += Var.strFiltreArticle;
     
                if (!string.IsNullOrEmpty(Var.strFiltreComposant))
                    strFiltresTemp += Var.strFiltreComposant;
     
                if (!string.IsNullOrEmpty(Var.strFiltreAgentOrdo))
                    strFiltresTemp += Var.strFiltreAgentOrdo;
     
                if (!string.IsNullOrEmpty(Var.strFiltreGestMRP))
                    strFiltresTemp += Var.strFiltreGestMRP;
     
                if (!string.IsNullOrEmpty(Var.strFiltreSquelette) && Var.strFiltreSquelette != "TOUS")
                    strFiltresTemp += Var.strFiltreSquelette + " SQUELETTE";
    Et en fin de code seulement modifier mes binding :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      Application.Current.Dispatcher.Invoke(new Action(() => LstOperations.Clear()));
                Application.Current.Dispatcher.Invoke(new Action(() => LstOperations.AddRange(_lstOperationsTemp)));
     
                strSelection = strSelectionTemp;
                strFiltres = strFiltresTemp;
                strTotaux = "Total retard : " + dblTotalJoursRetard.ToString() + " Jours     Nb OPs : " + dblTotalOp.ToString() + "     Qte totale : " + dblTotalQte.ToString() + " Pces     Temps total : " + dblTotalTemps + " Hrs";
    Malheureusement, le problème est toujours le même. sur mon PC, aucun soucis, sur un autre, je vois la liste disparaître et réapparaître. Ça m'a l'air un peu mieux, plus aléatoire, mais toujours le cas quand même. Même si c'est une fraction de seconde j'aimerais éviter.

    Comment faire ? Je ne vois nulle part d'autre d'endroit ou je modifie le binding

    Comme vous pouvez le voir en haut de ma fonction GetList, je mets le bouton ShowMenu à Hidden, puis je le remets à Visible à la fin.

    J'ai pu constater, que la liste ne disparait pas au moment ou je vois le bouton disparaitre, mais la liste disparait puis réapparait très vite seulement au moment ou le bouton réapparait également.

    Si je ne fais plus le clear de ma liste Application.Current.Dispatcher.Invoke(new Action(() => LstOperations.Clear())); ce comportement n'intervient plus sur aucun PC, ça fonctionne donc comme je le souhaite. Mais , bien entendu, ma liste se cumule au lieu de se réécraser.

    Comment faire ? Dois-je calculer un delta pour être totalement transparent ??

    Le .clear et .AddRange de la liste Temp n'étant apparemment pas assez rapide, malheureusement.

    Sur mon PC : quand je demande des données, la liste est visible quand il exécute ma fonction getlist, je peux même interagir avec l'application, ensuite je ne peux plus rien faire sur l'application pendant le temps ou il rafraichit le binding donc quand il a terminé la récupération de données.
    C'est ce comportement que je veux.

    Sur l'autre PC : il fait disparaitre puis réapparaitre la liste.

    Sur mon PC je peux prendre 3000 lignes, pas de disparition / réapparition de liste

    sur l'autre PC : je prends 1 seule ligne et ce comportement est la.

    Même puissance, même OS.

  11. #11
    Membre Expert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 056
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    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 056
    Par défaut
    Pour la forme du code, il te faut absolument respecter les conventions de nommages, à savoir les propriétés publiques doivent commencer par une majuscule. Ici impossible de différencier tes propriétés de classes et les variables de ta méthode.
    Ensuite il faut vraiment te forcer à éclater tes fonctions pour qu'elles soit le plus petite possible, en tout cas pourqu'elles ne fassent, dans la mesure du possible, qu'une seule chose. Ici tu peux avoir au moins une fonction qui prépare ton filtre, et au moins 2 autres qui préparent les différentes requête sql (et meme pour le sql il est courant de les mettres dans une autre classe), et encore une qui "traduit" le retour de ta BDD. Ca permet de comprendre et de déboguer 10 fois plus vite.

    Pour le fond je ne vois pas ou tu fais usages d'un 2nd thread et c'est ce qui me semble pose problème.
    Enfin c'est pas vraiment un problème, c'est juste que ton traitement prends du temps et donc tu figes ton interface. Selon la vélocité de ta machine (qui peut varier légerement si tu as d'autres programmes gourmand au meme moment) tu vas te retrouver à avoir une réactivité plus ou moins fluide. Et je me demande si pour le coup ton Dispatcher ne fait pas que débloquer la boucle du rendu.
    T'es bien sur d'etre dans une autre thread?

  12. #12
    Membre confirmé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2017
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2017
    Messages : 71
    Par défaut
    Salut

    Merci des conseils. Je tâcherai d'optimiser mon code.

    Oui j'en suis sûr :

    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
     
    Thread thrGetList;
     
    private void timer_Tick(object sender, EventArgs e)
            {
                iTimer--;
     
                if (iTimer == 0)
                {
                    thrGetList = new Thread(GetList);
                    thrGetList.Start();
                    dtTimer.Stop();
                    iTimer = 300;
                    dtTimer.Start();
                }
            }
    Je n'ai toujours pas d'explication quand au fait que je vois la liste disparaître et réapparaître sur un PC, mais pas sur l'autre malheureusement. C'est au moment du .Clear et .AddRange dans ma liste d'affichage..

    EDIT :: Par contre je viens de tester sans faire dans un nouveau Thread, appeler ma fonction juste en faisant GetList();

    Là, aucun problème d'affichage de liste, je ne vois rien disparaître / réapparaître. Alors certes, on ne peut plus utiliser l'interface pendant 5-10 secs (1/2 sec pour la plus part des cas) le temps que les données se rafraichissent (le temps dépend du nombre de lignes SQL) mais par contre plus de soucis de disparition de liste... Et mon bouton que je cache avec ma variable strShowMenu = "Hidden" en début de fonction et que je réaffiche en fin de fonction, forcément ne disparaît plus.

  13. #13
    Membre Expert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 056
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    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 056
    Par défaut
    J'ai pas d'environnement pour tester alors je ne suis pas certains de mon analyse.

    Lorsque tu exécutes ton code dans le thread principal ton IHM se fige tant que ta fonction n'est pas terminée, c'est donc normal et ça tu l'as bien intégré en voulant passer par un thread.

    Quand tu te trouves sur un autre thread il est interdit d'accéder à une propriété d'un objet de l'IHM sous peine d'avoir une exception, par exemple tu ne pourras pas faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monBouton.Content="un test autre thread"
    .
    C'est pour cela que souvent tu vas trouver des informations te disant d'utiliser le fameux Dispatcher.Invoke, ou Dispatcher.BeginInvoke. Le but de ces 2 méthodes et de passer ta demande au thread de l'IHM, qui lui a le droit d’accéder à ses objets.
    Le Invoke va bloquer le thread appelant jusqu'à ce que le thread IHM ai fini ses opérations, alors que le BeginInvoke va te retourner immédiatement sans garantis d'avoir exécuter ta demande (il l'a fera quand il pourra).

    Toi tu utilises le Binding pour lier des informations à ton IHM, et il se trouve que depuis la version 4.5 de WPF c'est possible probablement parce que le mécanisme de binding doit faire automatiquement un équivalent de Dispatcher.BeginInvoke().
    Ainsi lorsque tu fais,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strShowMenu = "Hidden";
    un message est probablement ajouté à la pile des Dispatcher pour lui dire de mettre à jour, quand il en a le temps... Or il n'en a pas le temps puisque tu continues jusqu'a ce qu'il rencontre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Application.Current.Dispatcher.Invoke(new Action(() => _lstOperationsTemp.Clear()));
    Là clairement tu dis d'effectuer ton Clear, et il en profite pour également mettre ) jour le binding lié à strShowMenu.
    Le bouton doit disparaitre à ce moment là.

    Je te propose donc de remplacer ta 1ere ligne par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ]Application.Current.Dispatcher.Invoke(new Action(() =>
    strShowMenu = "Hidden"));
    Ensuite ton 2eme problème c'est qu'explicitement tu dis effaces le contenus de la collection, puis remplis là. Je suspecte que le Clear génère des notifications dont tu n'as que faire pour ton cas et donc probablement que selon le pc ca prend plus ou moins de temps.
    Moi je remplacerais carrément ta LstOperations par ta collection temporaire, pour cela il faut pas oublier de faire un Set dans ton set , qui va permettre d'appeler INotifyPropertyChanged.

    -------
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            public static RangeObservableCollection<CL_Operation> _lstOperations = new RangeObservableCollection<CL_Operation>();
            public static RangeObservableCollection<CL_Operation> LstOperations
            {
                get { return _lstOperations; }
               set { Set( _lstOperations, value); }
            }

    [CODE]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Application.Current.Dispatcher.Invoke(new Action(() => LstOperations=_lstOperationsTemp)); 
                strSelection = strSelectionTemp;
                strFiltres = strFiltresTemp;
                strTotaux = "Total retard : " + dblTotalJoursRetard.ToString() + " Jours     Nb OPs : " + dblTotalOp.ToString() + "     Qte totale : " + dblTotalQte.ToString() + " Pces     Temps total : " + dblTotalTemps + " Hrs";
    ------
    Ou alors à la place tu peux essayer le ReplaceRange si ton RangeObservableCollection est bien la collection trouvé sur dvp.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Application.Current.Dispatcher.Invoke(new Action(() => LstOperations.ReplaceRange(0,_lstOperationsTemp)); 
                strSelection = strSelectionTemp;
                strFiltres = strFiltresTemp;
                strTotaux = "Total retard : " + dblTotalJoursRetard.ToString() + " Jours     Nb OPs : " + dblTotalOp.ToString() + "     Qte totale : " + dblTotalQte.ToString() + " Pces     Temps total : " + dblTotalTemps + " Hrs";

  14. #14
    Membre confirmé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2017
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2017
    Messages : 71
    Par défaut
    Bonjour et encore merci pour la réponse.

    Pour le strShowMenu, c'était plus pour cibler à quel moment ma liste disparaissait / réapparaissait. Pas de soucis avec lui pour le moment.

    Donc j'ai fait ton test :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Dispatcher.Invoke(new Action(() => LstOperations.ReplaceRange(_lstOperationsTemp)));
    Ça revient au même que ce que je faisais avant, il fait un Clear puis un Add

    1 fois sur 2 ou 1 fois sur 3 je vois la liste disparaître / réapparaître (toujours la même liste avec le même nombre de lignes : ce n'est pas un comportement régulier ....)

    Je n'arrive pas à faire un Set de dans mon set :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public static RangeObservableCollection<CL_Operation> _lstOperations = new RangeObservableCollection<CL_Operation>();
            public static RangeObservableCollection<CL_Operation> LstOperations
            {
                get { return _lstOperations; }
                set { Set(ref _lstOperations, value) ; }
            }
    Une référence d'objet est requise pour la propriété, la méthode ou le champ non statique 'Plutus.MainWindow.Set<TValue>(ref TValue, TValue, string)'

    Conclusion : pour l'instant, toujours ce problème, plus aléatoire par contre.

    Seul moyen pour ne pas voir la liste disparaître et réapparaître que j'ai trouvé pour l'instant : ne pas travailler dans un nouveau thread mais rester dans le même que l'application.

    Merci encore.

  15. #15
    Membre Expert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 056
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    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 056
    Par défaut
    Citation Envoyé par Fellerson Voir le message
    Une référence d'objet est requise pour la propriété, la méthode ou le champ non statique 'Plutus.MainWindow.Set<TValue>(ref TValue, TValue, string)'
    Effectivement je n'avais pas remarqué le static. Il y a une raison à ca? Tu ne t'abonnes à aucun évenement de ta collection via une autre classe?

    Mais je pense avoir trouvé ton soucis.
    Le probleme de performance vient surement du control ItemsControl qui n'implémente pas par défaut de virtualisation. Du coup wpf calcul l'ensemble des objets de ta collection.
    A vu de nez tu devrais enlever ton Scrollviewer et remplacer ton ItemsControl par une ListBox qui contient déjà un scrollviewer et qui en plus gères la virtualisation.
    Si pour une raison quelconque tu dois quand même utiliser l'ItemsControl, jètes un œil à ce commentaire qui traite la question : https://stackoverflow.com/questions/...n-itemscontrol

  16. #16
    Membre confirmé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2017
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2017
    Messages : 71
    Par défaut
    Merci pour ta réponse.

    Je pense que je peux enlever le static effectivement.

    Sinon, non je ne peux pas remplacer mon ItemsControl par une ListBox car ça casse tout mon layout malheureusement..........

    J'essaie de voir comment implémenter ta solution. Je ne vois pas trop pour l'instant ce dont j'ai besoin dedans

    EDIT :

    Le fait d'avoir implémenté ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <ItemsControl Grid.ColumnSpan="3" ScrollViewer.CanContentScroll="True" VirtualizingPanel.IsVirtualizing="True" VerticalAlignment="Top" x:Name="lvDataBinding" HorizontalContentAlignment="Stretch" BorderThickness="0" Margin="10" Grid.Row="3" Background="{x:Null}" ItemsSource="{Binding LstOperations}" Foreground="White">
    A l'air d'avoir résolu mon problème

    Merci BEAUCOUP.

Discussions similaires

  1. WPF (résolution écran)
    Par JFJ54 dans le forum Windows Presentation Foundation
    Réponses: 2
    Dernier message: 07/04/2014, 15h14
  2. WPF et écran tactile
    Par Lenn0x dans le forum Windows Presentation Foundation
    Réponses: 5
    Dernier message: 24/07/2012, 10h22
  3. WPF MEF et écran de login
    Par CaptainChoc dans le forum Windows Presentation Foundation
    Réponses: 7
    Dernier message: 17/01/2012, 11h19
  4. [WPF][MultiThreading/Composants] Petit probleme de conception ?
    Par chico200987 dans le forum Windows Presentation Foundation
    Réponses: 5
    Dernier message: 15/08/2010, 19h02
  5. Multithread en WPF
    Par Herwin78800 dans le forum Windows Presentation Foundation
    Réponses: 13
    Dernier message: 01/09/2009, 19h56

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