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

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

Windows Presentation Foundation Discussion :

Filtrage en cascade de comboboxs en WPF XAML .NET


Sujet :

Windows Presentation Foundation

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut Filtrage en cascade de comboboxs en WPF XAML .NET
    Bonjour,

    Je viens du forum WinForms où j'avais déjà bien avancé un projet de conversion en VB.NET WinForms d'un comparateur développé sous Excel: un membre du forum m'avait conseillé de repartir à 0 en WPF pour faire la même chose en beaucoup + simple et + de possibilités (en particulier Comboboxs à 2 colonnes, ou encore infobulles imagées sur mousehover d'un item de combobox).

    Donc j'ai suivi son conseil mais j'avoue j'ai du mal pour filtrer mes vues de datasets (créées auto par VB2010).

    Pour l'instant voilà ce que j'ai dans le code XAML :
    Code xml : 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
    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Final Fantasy XI Melee Damage Comparator v6.0" Name="MainWindow" Height="768" Width="1024" MinHeight="600" MinWidth="800" WindowStartupLocation="CenterScreen" WindowStyle="ThreeDBorderWindow" Icon="/FFXIMDCwpf1;component/Images/PoroggoIcon.jpg" xmlns:my="clr-namespace:WpfApplication1">
        <Window.Resources>
            <my:DataSet x:Key="DataSet" />
            <CollectionViewSource x:Key="JobsListViewSource" Source="{Binding Path=JobsList, Source={StaticResource DataSet}}" />
            <CollectionViewSource x:Key="WeaponViewSource" Source="{Binding Path=Weapon, Source={StaticResource DataSet}}" />
        </Window.Resources>
        <Grid Name="Compare">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="350" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <StackPanel Name="CompareInputs" Grid.Column="0" >
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="50" />
                        <ColumnDefinition />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                    <TextBlock Name="Setup1" Grid.Column="1" Text="Setup 1" TextAlignment="Center" FontWeight="Bold" FontSize="14" />
                    <TextBlock Name="Setup2" Grid.Column="2" Text="Setup 2" TextAlignment="Center" FontWeight="Bold" FontSize="14" />              
                </Grid>
                <Expander Name="Expander1" Header="Race, Jobs and Levels" IsExpanded="True" Background="{x:Null}">
                    <Grid DataContext="{StaticResource JobsListViewSource}">
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50"/>
                            <ColumnDefinition />
                            <ColumnDefinition Width="25"/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Row="0" Grid.Column="0" Margin="2">Race</TextBlock>
                        <ComboBox Name="Race1" Grid.Column="1" Grid.ColumnSpan="2" VerticalContentAlignment="Center" Margin="2" Background="{x:Null}" BorderThickness="0" BorderBrush="{x:Null}" IsSynchronizedWithCurrentItem="False">
                            <ComboBoxItem Content="Elvaan"/>
                            <ComboBoxItem Content="Galka"/>
                            <ComboBoxItem Content="Hume"/>
                            <ComboBoxItem Content="Mithra"/>
                            <ComboBoxItem Content="Tarutaru"/>
                        </ComboBox>
                        <TextBlock Grid.Row="1" Grid.Column="0" Margin="2">MainJob</TextBlock>
                        <ComboBox Name="MainJob" Grid.Row="1" Grid.Column="1" Margin="2,2,0,2" Background="{x:Null}" BorderBrush="{x:Null}" DisplayMemberPath="Names" SelectedValuePath="Jobs" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="False"/>
                        <TextBox Name="MainLevel" Grid.Row="1" Grid.Column="2" MaxLength="2" BorderBrush="{x:Null}" Text="00" />
                        <TextBlock Grid.Row="2" Grid.Column="0" Margin="2">SubJob</TextBlock>
                        <ComboBox Name="SubJob" Grid.Row="2" Grid.Column="1" Margin="2,2,0,2" Background="{x:Null}" BorderBrush="{x:Null}" DisplayMemberPath="Names" SelectedValuePath="Jobs" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="False"/>
                        <TextBox Name="SubLevel" Grid.Row="2" Grid.Column="2" MaxLength="2" BorderBrush="{x:Null}" Text="00" />
                    </Grid>
                </Expander>
                <Expander Name="Expander2" Header="TP Sets" IsExpanded="True">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50"/>
                            <ColumnDefinition />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <Menu Grid.Row="0" Grid.Column="0" Margin="2" ToolTip="Edit Database or Search Filter">
                            <Menu.Background>
                                <ImageBrush ImageSource="/FFXIMDCwpf1;component/Images/AxeIcon.jpg" Stretch="Uniform" />
                            </Menu.Background>
                            <MenuItem Height="22" Width="44">
                                <MenuItem Header="Edit Database" />
                                <MenuItem Header="Search Filter">
                                    <MenuItem Header="Axes" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Clubs" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Daggers" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Katanas" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Swords" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Great Axes" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Great Swords" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Great Katanas" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Polearms" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Scythes" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Staves" IsCheckable="True" StaysOpenOnClick="True"/>
                                </MenuItem>
                            </MenuItem>
                        </Menu>
                        <ComboBox Name="MainWeapon1" Grid.Row="0" Grid.Column="1" VerticalContentAlignment="Center" IsEditable="True" IsReadOnly="True" Margin="2" BorderBrush="{x:Null}" DisplayMemberPath="Names" ItemsSource="{Binding Source={StaticResource WeaponViewSource}}" IsSynchronizedWithCurrentItem="False" />                    
                        <ComboBox Name="MainWeapon2" Grid.Row="0" Grid.Column="2" VerticalContentAlignment="Center" IsEditable="True" IsReadOnly="True" Margin="2" BorderBrush="{x:Null}" DisplayMemberPath="Names" ItemsSource="{Binding Source={StaticResource WeaponViewSource}}" IsSynchronizedWithCurrentItem="False" />
                        <Menu Grid.Row="1" Grid.Column="0" Margin="2" ToolTip="Edit Database or Search Filter">
                            <Menu.Background>
                                <ImageBrush ImageSource="/FFXIMDCwpf1;component/Images/SwordIcon.jpg" Stretch="Uniform" />
                            </Menu.Background>
                            <MenuItem Height="22" Width="44">
                                <MenuItem Header="Edit Database" />
                                <MenuItem Header="Search Filter">
                                    <MenuItem Header="Axes" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Clubs" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Daggers" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Katanas" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Swords" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Grips" IsCheckable="True" StaysOpenOnClick="True"/>
                                    <MenuItem Header="Shields" IsCheckable="True" StaysOpenOnClick="True"/>
                                </MenuItem>
                            </MenuItem>
                        </Menu>
                        <ComboBox Name="SubWeapon1" Grid.Row="1" Grid.Column="1" VerticalContentAlignment="Center" IsEditable="True" IsReadOnly="True" Margin="2" BorderBrush="{x:Null}" DisplayMemberPath="Names" ItemsSource="{Binding Source={StaticResource WeaponViewSource}}" IsSynchronizedWithCurrentItem="False"/>
                        <ComboBox Name="SubWeapon2" Grid.Row="1" Grid.Column="2" VerticalContentAlignment="Center" IsEditable="True" IsReadOnly="True" Margin="2" BorderBrush="{x:Null}" DisplayMemberPath="Names" ItemsSource="{Binding Source={StaticResource WeaponViewSource}}" IsSynchronizedWithCurrentItem="False"/>
                        <Menu Grid.Row="2" Grid.Column="0" Margin="2" ToolTip="Edit Database">
                            <Menu.Background>
                                <ImageBrush ImageSource="/FFXIMDCwpf1;component/Images/BowIcon.jpg" Stretch="Uniform" />
                            </Menu.Background>
                            <MenuItem Height="22" Width="44"/>
                        </Menu>
                    </Grid>
                </Expander>
            </StackPanel>
            <TabControl Name="CompareOutputs" Grid.Column="1" />
        </Grid>
    </Window>

    ...et dans le code behind (.vb):
    Code vb.net : 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
    Class MainWindow
     
        Private Sub MainWindow_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
            Dim DataSet As WpfApplication1.DataSet = CType(Me.FindResource("DataSet"), WpfApplication1.DataSet)
            'Chargez les données dans la table JobsList. Vous pouvez modifier ce code si nécessaire.
            Dim DataSetJobsListTableAdapter As WpfApplication1.DataSetTableAdapters.JobsListTableAdapter = New WpfApplication1.DataSetTableAdapters.JobsListTableAdapter()
            DataSetJobsListTableAdapter.Fill(DataSet.JobsList)
            Dim JobsListViewSource As System.Windows.Data.CollectionViewSource = CType(Me.FindResource("JobsListViewSource"), System.Windows.Data.CollectionViewSource)
            JobsListViewSource.View.MoveCurrentToFirst()
            'Chargez les données dans la table Weapon. Vous pouvez modifier ce code si nécessaire.
            Dim DataSetWeaponTableAdapter As WpfApplication1.DataSetTableAdapters.WeaponTableAdapter = New WpfApplication1.DataSetTableAdapters.WeaponTableAdapter()
            DataSetWeaponTableAdapter.Fill(DataSet.Weapon)
            Dim WeaponViewSource As System.Windows.Data.CollectionViewSource = CType(Me.FindResource("WeaponViewSource"), System.Windows.Data.CollectionViewSource)
            WeaponViewSource.View.MoveCurrentToFirst()
        End Sub
    End Class

    Ces codes fonctionnent mais les comboboxs ne sont pas filtrées (et donc TRES longues pour certaines) rendant l'utilisation de l'UI vraiment fastidieuse...

    Les datatables utilisées ont le format suivant :
    - JobsList (Jobs, Names): Jobs est une colonne contenant les métiers en toutes lettres, Names est la 2e colonne avec les codes métiers correspondants (utilisée en SelectedValue).
    - Weapon (Names, Equippable Jobs, Level, RareTag, ....)
    Nota: j'ai également 15 autres datatables non mentionées ici mais même format que Weapon.

    Les différents filtrages souhaités sont :
    1) Cbx MainJob Source="JobsListViewSource.Jobs" Filter= <> SubJob.value
    2) idem pour Cbx Subjob filtrée <> MainJob.value
    3) Cbx MainWeapon1 Source="WeaponViewSource.Names" Filter=AND[isnumber(find(MainJob.SelectedValue, WeaponViewSource.EquippableJobs)), WeaponViewSource.Level<=MainLevel.value, si(WeaponviewSource.Names(SubWeapon1).RareTag="YES", "<>SubWeapon1")]
    3bis) Idem pour la cbx MainWeapon2 mais avec SubWeapon2 (au lieu de 1)
    4 et 4bis) idem que les filtrages 3 et 3bis mais appliquées pour les cbx Subweapon1 et 2 par rapport aux cbx MainWeapon1 & 2 resp.

    En gros, je cherche à faire du filtrage exclusif bi-directionnel entre 2 comboboxs, en XAML (si possible avec 0 code behind).
    D'après mes recherches je n'ai trouvé qu'une phrase sur MSDN (pas d'exemple):
    Use CollectionViewSource object to benefit from sorting and filtering functionalities
    ...mais sur 2 threads sur ce même forum, j'ai trouvé une syntaxe ressemblant à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <CollectionViewSource Filter="" ... />
    mais c'est tout...

    L'autre question, d'ordre structural pour essayer d'écrire un code XAML "propre", est : Serait-il possible de mettre les <CollectionViewSource .../> dans le <RowDefinition /> contenant les comboboxs se servant de cette View ? (au lieu de mettre toutes les vues dans le Windows.Ressources). je n'ai pas réussi avec DataContext= , Binding=, Source= , etc...

    Merci d'avance

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    J'ai trouvé 2 liens qui se rapportent à ce que je veux faire :
    FilterEventHandler
    CustomFilter

    Le 2e me parait l'ideal mais quand j'ai lu les notes, on dirait que ca ne marchera pas du tout dans mon cas...

    Bon.... pas vraiment le choix, je me tente avec la 1ère approche :
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
        <Window.Resources>
            <my:DataSet x:Key="DataSet" />
            <CollectionViewSource x:Key="MainJobsListViewSource" Source="{Binding Path=JobsList, Source={StaticResource DataSet}}" Filter="MainJobsListView_Filter"/>
            <CollectionViewSource x:Key="SubJobsListViewSource" Source="{Binding Path=JobsList, Source={StaticResource DataSet}}" Filter="SubJobsListView_Filter"/>
            <CollectionViewSource x:Key="FoodViewSource" Source="{Binding Path=Food, Source={StaticResource DataSet}}" />
            <CollectionViewSource x:Key="BuffsViewSource" Source="{Binding Path=Buffs, Source={StaticResource DataSet}}" />
            <CollectionViewSource x:Key="MainWeapon1ListViewSource" Source="{Binding Path=Weapon, Source={StaticResource DataSet}}" Filter="MainWeapon1View_Filter"/>
            <CollectionViewSource x:Key="SubWeapon1ListViewSource" Source="{Binding Path=Weapon, Source={StaticResource DataSet}}" Filter="SubWeapon1View_Filter"/>
            <CollectionViewSource x:Key="MainWeapon2ListViewSource" Source="{Binding Path=Weapon, Source={StaticResource DataSet}}" Filter="MainWeapon2View_Filter"/>
            <CollectionViewSource x:Key="SubWeapon2ListViewSource" Source="{Binding Path=Weapon, Source={StaticResource DataSet}}" Filter="SubWeapon2View_Filter"/>
        </Window.Resources>
     
    ...
     
    <ComboBox Name="MainJob" Grid.Row="1" Grid.Column="1" Margin="2,2,0,2" Background="{x:Null}" BorderBrush="{x:Null}" DisplayMemberPath="Names" SelectedValuePath="Jobs" ItemsSource="{Binding Source={StaticResource MainJobsListViewSource}}" IsSynchronizedWithCurrentItem="False"/>
    <ComboBox Name="SubJob" Grid.Row="2" Grid.Column="1" Margin="2,2,0,2" Background="{x:Null}" BorderBrush="{x:Null}" DisplayMemberPath="Names" SelectedValuePath="Jobs" ItemsSource="{Binding Source={StaticResource SubJobsListViewSource}}" IsSynchronizedWithCurrentItem="False"/>
     
    ...
     
    <ComboBox Name="MainWeapon1" Grid.Row="0" Grid.Column="1" VerticalContentAlignment="Center" IsEditable="True" Margin="2" BorderBrush="{x:Null}" DisplayMemberPath="Names" ItemsSource="{Binding Source={StaticResource MainWeapon1ListViewSource}}" IsSynchronizedWithCurrentItem="False"/>
    <ComboBox Name="MainWeapon2" Grid.Row="0" Grid.Column="2" VerticalContentAlignment="Center" IsEditable="True" Margin="2" BorderBrush="{x:Null}" DisplayMemberPath="Names" ItemsSource="{Binding Source={StaticResource SubWeapon1ListViewSource}}" IsSynchronizedWithCurrentItem="False"/>
    ...
    <ComboBox Name="SubWeapon1" Grid.Row="1" Grid.Column="1" VerticalContentAlignment="Center" IsEditable="True" Margin="2" BorderBrush="{x:Null}" DisplayMemberPath="Names" ItemsSource="{Binding Source={StaticResource MainWeapon2ListViewSource}}" IsSynchronizedWithCurrentItem="False"/>
    <ComboBox Name="SubWeapon2" Grid.Row="1" Grid.Column="2" VerticalContentAlignment="Center" IsEditable="True" Margin="2" BorderBrush="{x:Null}" DisplayMemberPath="Names" ItemsSource="{Binding Source={StaticResource SubWeapon1ListViewSource}}" IsSynchronizedWithCurrentItem="False"/>

    et dans le code .vb :
    Code vb.net : 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
    Class MainWindow
     
        Private Sub MainWindow_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
    ...
        End Sub
     
        Private Sub MainJobsListView_Filter(ByVal sender As System.Object, ByVal e As System.Windows.Data.FilterEventArgs)
            If e.Item = SubJob.SelectedItem Then
                e.Accepted = False
            Else : e.Accepted = True
            End If
        End Sub
     
        Private Sub SubJobsListView_Filter(ByVal sender As System.Object, ByVal e As System.Windows.Data.FilterEventArgs)
            If e.Item = MainJob.SelectedItem Then
                e.Accepted = False
            Else : e.Accepted = True
            End If
        End Sub
     
        Private Sub MainWeapon1View_Filter(ByVal sender As System.Object, ByVal e As System.Windows.Data.FilterEventArgs)
            If e.Item = SubWeapon1.SelectedItem Then
                e.Accepted = False
            Else : e.Accepted = True
            End If
        End Sub
     
        Private Sub SubWeapon1View_Filter(ByVal sender As System.Object, ByVal e As System.Windows.Data.FilterEventArgs)
            If e.Item = MainWeapon1.SelectedItem Then
                e.Accepted = False
            Else : e.Accepted = True
            End If
        End Sub
     
        Private Sub MainWeapon2View_Filter(ByVal sender As System.Object, ByVal e As System.Windows.Data.FilterEventArgs)
            If e.Item = SubWeapon2.SelectedItem Then
                e.Accepted = False
            Else : e.Accepted = True
            End If
        End Sub
     
        Private Sub SubWeapon2View_Filter(ByVal sender As System.Object, ByVal e As System.Windows.Data.FilterEventArgs)
            If e.Item = MainWeapon2.SelectedItem Then
                e.Accepted = False
            Else : e.Accepted = True
            End If
        End Sub
    End Class

    Mais ca marche pas (listes déroulantes vides)

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Sinon, j'ai aussi trouvé une autre approche, mais je ne sait pas si elle peut s'appliquer au filtrage de Combobox.Datasources :
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
                            <ComboBox Name="MainJob" ItemsSource="{Binding Source={StaticResource JobsListViewSource}}" IsSynchronizedWithCurrentItem="False">
                                <ComboBox.Triggers>
                                    <EventTrigger RoutedEvent="ComboBox.SelectionChanged">
                                        <EventTrigger.Actions>
                                            <!-- Quelle action appliquer pour re-filtrer la CollectionViewSource de la CBX "SubJob" SANS la valeur qui vient d'etre sélectionnée ? -->
                                        </EventTrigger.Actions>
                                    </EventTrigger>
                                </ComboBox.Triggers>

    ...sinon peut être avec <DataTrigger...> ?

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Quelqu'un aurait-il un exemple utilisant la proprièté CustomFilter s.v.p. ?

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    à priori le filtrage se fait sur la propriété View d'un CollectionViewSource
    coté code behind ca demande un predicate(of object) donc l'équivalent d'une fonction qui recoit un objet et qui retourne un booléen pour dire si le filtre accepte l'instance

    et à priori le filtrage doit être averti d'un changement pour se recalculer (<view>.refresh) à utiliser donc sur l'évènementiel du combobox qui modifie l'affichage d'un autre

    je sais pas si ca aide ... je suis pas expert en wpf, j'ai encore pas mal de code behind ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Oui j'avais lu ce que tu pense pendant mes recherches, mais apparemment faut pas utiliser CollectionViewSource dans la mesure où la mise à jour(filtrage) de la vue bindée à une des comboboxs provoquera aussi la mise à jour de toutes les autres vues suivant la même règle de filtrage, ce que je ne veux pas !

    Donc déjà je crois faudrait que je CTYPE mes datables en BindingListCollectionView ? ou un autre type prenant en charge INOTIFYCOLLECTIONCHANGED ?

    Ensuite je ne sait pas non plus quel type de collection supporte aussi la propriètè CUSTOMFILTER qui me semble bien pratique car me suffirait de rentrer dans le xaml les chaînes string correspondant au filtrage de la combobox target.
    L'autre solution que j'envisage dans l'immédiat est :
    - dans le xaml :
    Code xaml : Sélectionner tout - Visualiser dans une fenêtre à part
    <Combobox  SelectionChanged="UpdateCBXItemsSources"/>
    - dans le code behind :
    Code vb.net : 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
        Private Sub UpdateCBXItemsSources(ByVal sender As ComboBox, ByVal e As SelectionChangedEventArgs)
            Select Case sender.Name
                Case Is = MainJob.Name
                    ' Filtrer : SubJob, toutes les cbx equipements(sur champ "Jobs"), et JobAbilities1 & 2
                Case Is = MainLevel.Name
                    ' Filtrer : SubLevel, toutes les cbx equipements(champ "MinLevel"), et JobAbilities1 & 2
                Case Is = SubJob.Name
                    ' Filtrer : MainJob, et JobAbilities1 & 2
                Case Is = SubLevel.Name
                    ' Filtrer : JobAbilities1 & 2
                Case Is = MainWeapon1.Name
                    ' Filtrer : SubWeapon1, WeaponSkills1
                Case Is = MainWeapon2.Name
                    ' Filtrer :
                Case Is = SubWeapon1.Name
                    ' Filtrer :
                Case Is = SubWeapon2.Name
                    ' Filtrer :
                Case Is = RangedWeapon1.Name
                    ' Filtrer :
                Case Is = RangedWeapon2.Name
                    ' Filtrer :
                Case Is = LeftEarTP1.Name
                    ' Filtrer :
                Case Is = LeftEarTP2.Name
                    ' Filtrer :
                Case Is = RightEarTP1.Name
                    ' Filtrer :
                Case Is = RightEarTP2.Name
                    ' Filtrer :
                Case Is = LeftRingTP1.Name
                    ' Filtrer :
                Case Is = LeftRingTP2.Name
                    ' Filtrer :
                Case Is = RightRingTP1.Name
                    ' Filtrer :
                Case Is = RightRingTP2.Name
     
            End Select
        End Sub

    Enfin, la dernière chose que j'ai découvert pendant mes recherches, c'est la notion de MASTER-DETAIL, mais je suis loin d'en avoir compris l'application concrète.

    Donc voilà où j'en suis, en gros rien n'avance

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    J'ai trouvé ce matin un article sur Google avec CustomFilter et ADO.net.

    En me basant dessus, j'ai supprimé toutes les resources dans le xaml, mais rajouté à chaque combobox : DataContext=NomComboboxBindingList ItesmSource={Binding} SelectionChanged="UpdateCBXItemsSources".
    Puis dans le code behind :
    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
    Class MainWindow
     
        Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles MyBase.Loaded
            Dim DataSet As WpfApplication1.DataSet = CType(Me.FindResource("DataSet"), WpfApplication1.DataSet)
            'Chargez les données dans la table JobsList.
            Dim DataSetJobsListTableAdapter As WpfApplication1.DataSetTableAdapters.JobsListTableAdapter = New WpfApplication1.DataSetTableAdapters.JobsListTableAdapter()
            DataSetJobsListTableAdapter.Fill(DataSet.JobsList)
            'Chargez les données dans la table Food.
            Dim DataSetFoodTableAdapter As WpfApplication1.DataSetTableAdapters.FoodTableAdapter = New WpfApplication1.DataSetTableAdapters.FoodTableAdapter()
            DataSetFoodTableAdapter.Fill(DataSet.Food)
            'Chargez les données dans la table Buffs.
            Dim DataSetBuffsTableAdapter As WpfApplication1.DataSetTableAdapters.BuffsTableAdapter = New WpfApplication1.DataSetTableAdapters.BuffsTableAdapter()
            DataSetBuffsTableAdapter.Fill(DataSet.Buffs)
            'Chargez les données dans la table Weapon.
            Dim DataSetWeaponTableAdapter As WpfApplication1.DataSetTableAdapters.WeaponTableAdapter = New WpfApplication1.DataSetTableAdapters.WeaponTableAdapter()
            DataSetWeaponTableAdapter.Fill(DataSet.Weapon)
        End Sub
     
        ' Création des BindingCollectionView (supportant INotifyCollectionChanged et CustomFilter) qui serviront d'ItemsSource aux Comboboxs.
        Dim MainJobBindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(DataSet.JobsList), BindingListCollectionView)
        Dim SubJobBindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(DataSet.JobsList), BindingListCollectionView)
        Dim MainWeapon1BindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(DataSet.Weapon), BindingListCollectionView)
        Dim MainWeapon2BindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(DataSet.Weapon), BindingListCollectionView)
        Dim SubWeapon1BindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(DataSet.Weapon), BindingListCollectionView)
        Dim SubWeapon2BindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(DataSet.Weapon), BindingListCollectionView)
     
        Private Sub UpdateCBXItemsSources(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Select Case sender.Name
                Case "MainJob" Or "MainLevel"
                    ' Verifier si MainLevel <= 90
                    If CUInt(MainLevel.Text) > 90 Then
                        MainLevel.Text = "90"
                    End If
                    ' Verifier si SubLevel <= MainLevel/2
                    If CUInt(SubLevel.Text) > Math.Floor(CUInt(MainLevel.Text) / 2) Then
                        SubLevel.Text = Math.Floor(CUInt(MainLevel.Text) / 2).ToString
                    End If
                    ' Filtrer : SubJob, toutes les cbx equipements, et JobAbilities1 & 2
                    SubJobBindingList.CustomFilter = "Jobs <>'" & MainJob.SelectedValue & "'"
                    MainWeapon1BindingList.CustomFilter = "( [Equippable Jobs] LIKE '*" & MainJob.SelectedValue & "*|ALL'" &
                                                          "AND Level <= '" & CUInt(MainLevel.Text) & "'" &
                                                          "AND NOT( Names = '" & Replace(SubWeapon1.Text, "'", "''") & "' AND [Rare Tag] = 'True' )"
                    SubWeapon1BindingList.CustomFilter = "( [Equippable Jobs] LIKE '*" & MainJob.SelectedValue & "*|ALL'" &
                                                         "AND Level <= '" & CUInt(MainLevel.Text) & "'" &
                                                         "AND NOT( Names = '" & Replace(MainWeapon1.Text, "'", "''") & "' AND [Rare Tag] = 'True' )"
                    MainWeapon2BindingList.CustomFilter = "( [Equippable Jobs] LIKE '*" & MainJob.SelectedValue & "*|ALL'" &
                                                          "AND Level <= '" & CUInt(MainLevel.Text) & "'" &
                                                          "AND NOT( Names = '" & Replace(SubWeapon2.Text, "'", "''") & "' AND [Rare Tag] = 'True' )"
                    SubWeapon2BindingList.CustomFilter = "( [Equippable Jobs] LIKE '*" & MainJob.SelectedValue & "*|ALL'" &
                                                         "AND Level <= '" & CUInt(MainLevel.Text) & "'" &
                                                         "AND NOT( Names = '" & Replace(MainWeapon2.Text, "'", "''") & "' AND [Rare Tag] = 'True' )"
                Case "SubJob" Or "SubLevel"
                    ' Verifier si SubLevel <= MainLevel/2
                    If CUInt(SubLevel.Text) > Math.Floor(CUInt(MainLevel.Text) / 2) Then
                        SubLevel.Text = Math.Floor(CUInt(MainLevel.Text) / 2).ToString
                    End If
                    ' Filtrer : MainJob, et JobAbilities1 & 2
                    MainJobBindingList.CustomFilter = "Jobs <>'" & SubJob.SelectedValue & "'"
                Case "MainWeapon1"
                    ' Filtrer : SubWeapon1, WeaponSkills1
                Case "MainWeapon2"
                    ' Filtrer : SubWeapon2, WeaponSkills2
                Case "SubWeapon1"
                    ' Filtrer :
                Case "SubWeapon2"
                    ' Filtrer :
                Case "RangedWeapon1"
                    ' Filtrer :
                Case "RangedWeapon2"
                    ' Filtrer :
                Case "LeftEarTP1"
                    ' Filtrer :
                Case "LeftEarTP2"
                    ' Filtrer :
                Case "RightEarTP1"
                    ' Filtrer :
                Case "RightEarTP2"
                    ' Filtrer :
                Case "LeftRingTP1"
                    ' Filtrer :
                Case "LeftRingTP2"
                    ' Filtrer :
                Case "RightRingTP1"
                    ' Filtrer :
                Case "RightRingTP2"
                    ' Filtrer :
                Case "LeftEarWS1"
                    ' Filtrer :
                Case "LeftEarWS2"
                    ' Filtrer :
                Case "RightEarWS1"
                    ' Filtrer :
                Case "RightEarWS2"
                    ' Filtrer :
                Case "LeftRingWS1"
                    ' Filtrer :
                Case "LeftRingWS2"
                    ' Filtrer :
                Case "RightRingWS1"
                    ' Filtrer :
                Case "RightRingWS2"
                    ' Filtrer :
                Case Else
            End Select
        End Sub
    End Class
    Mais j'ai maintenant un problème de syntaxe dans le code de création des BindingListCollectionViews. VB2010 me surligne "Dataset.NomDatatable" avec l'erreur :
    Une référence à un membre non partagé requiert une référence d'objet.
    J'avoue j'ai encore du mal avec les bindings et déclarations, d'autant plus que VB2010 m'a importé toutes mes tables automatiquement et du coup je ne sait pas où il a mis les déclarations correspondantes et leur portée (afin d'essayer de résoudre cette erreur ?).

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Question: suis-je dans le bon forum ou c'est trop compliqué ou encore pas assez clair ?

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    en théorie c'est sur le bon forum ... ton topic a eut plus de 200 affichages ...

    à mon avis le truc c'est que ce que tu veux faire n'est pas pour débutant et paradoxalement tu utilises un dataset qui pour moi est une objet pour débutant
    donc si des gens ont fait des choses similaires ce n'est peut etre pas sur des datasets
    personnellement j'utilise des observablecollection, des classes héritant de dependecyobject ou implémentant inotifypropertychanged, et je code moi même les requetes


    à ta place je tenterais sur un autre sous forum à tout hasard (en délestant celui là éventuellement)
    histoire de trouver un autre public ... genre vb.net ou c#, chez c# y a du bon et tu peux leur mettre du code converti via http://www.developerfusion.com/tools.../vb-to-csharp/
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Bon... après pas mal de tatonnements, j'ai enfin réussi à binder et filtrer mes comboboxitems correctement.

    Dans le code XAML, pratiquement rien :
    Code xaml : 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
        <Window.Resources>
        </Window.Resources>
                        <Expander Name="RaceJobLevels" Header="Race, Jobs and Levels" IsExpanded="True" Background="{x:Null}"> <!-- Ici sont les ComboBoxs "Master" -->
                            <DockPanel>
                                <StackPanel DockPanel.Dock="Left">
                                    <TextBlock HorizontalAlignment="Center">Race</TextBlock>
                                    <ComboBox Name="Race" Width="80" VerticalAlignment="Center" HorizontalContentAlignment="Center" Background="{x:Null}" BorderThickness="0" BorderBrush="{x:Null}" SelectedIndex="0">
                                        <ComboBoxItem Content="Elvaan"/>
                                        <ComboBoxItem Content="Galka"/>
                                        <ComboBoxItem Content="Hume"/>
                                        <ComboBoxItem Content="Mithra"/>
                                        <ComboBoxItem Content="Tarutaru"/>
                                    </ComboBox>
                                </StackPanel>
                                <StackPanel Width="135">
                                    <TextBlock HorizontalAlignment="Center">Main Job/Level</TextBlock>
                                    <StackPanel Orientation="Horizontal">
                                        <ComboBox Name="MainJob" HorizontalContentAlignment="Center" Width="110" Background="{x:Null}" BorderBrush="{x:Null}" SelectionChanged="UpdateCBXItemsSources" DisplayMemberPath="Names" SelectedValuePath="Jobs" ItemsSource="{Binding}" SelectedIndex="0"/>
                                        <TextBox Name="MainLevel" HorizontalContentAlignment="Center" Width="22" Text="90" MaxLength="2" BorderBrush="{x:Null}" TextChanged="UpdateCBXItemsSources"/>
                                    </StackPanel>
                                </StackPanel>
                                <StackPanel Width="135">
                                    <TextBlock HorizontalAlignment="Center">Sub Job/Level</TextBlock>
                                    <StackPanel Orientation="Horizontal">
                                        <ComboBox Name="SubJob" HorizontalContentAlignment="Center" Width="110" Background="{x:Null}" BorderBrush="{x:Null}" SelectionChanged="UpdateCBXItemsSources" DisplayMemberPath="Names" SelectedValuePath="Jobs" ItemsSource="{Binding}"/>
                                        <TextBox Name="SubLevel" HorizontalContentAlignment="Center" Width="22" Text="00" MaxLength="2" BorderBrush="{x:Null}" TextChanged="UpdateCBXItemsSources"/>
                                    </StackPanel>
                                </StackPanel>
                            </DockPanel>
                        </Expander>
                        <Expander Name="TPsets" Header="TP Sets" IsExpanded="True"> <!-- Ici sont les ComboBoxs "Slaves" -->
                            <Expander.Resources>
                                <Style TargetType="ComboBox">
                                    <Setter Property="Background" Value="{x:Null}"/>
                                    <Setter Property="BorderBrush" Value="{x:Null}"/>
                                    <Setter Property="VerticalContentAlignment" Value="Center"/>
                                    <Setter Property="Margin" Value="2"/>
                                    <Setter Property="IsEditable" Value="True"/>
                                    <Setter Property="StaysOpenOnEdit" Value="True"/>
                                    <Setter Property="ItemsSource" Value="{Binding}"/>
                                    <Setter Property="DisplayMemberPath" Value="Names"/>
                                    <Setter Property="SelectedValuePath" Value="Names"/>
                                    <EventSetter Event="SelectionChanged" Handler="UpdateCBXItemsSources"/>
                                </Style>
                                <Style TargetType="ComboBoxItem">
                                    <Style.Triggers>
                                        <Trigger Property="IsMouseOver" Value="True">
                                            <Setter Property="ToolTip" Value="{Binding Description}"/> <!-- Tooltip descriptive dynamique -->
                                        </Trigger>
                                    </Style.Triggers>
                                </Style>
                            </Expander.Resources>
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition />
                                    ...
                                    <RowDefinition />
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="50"/>
                                    <ColumnDefinition />
                                    <ColumnDefinition />
                                </Grid.ColumnDefinitions>
                                <Menu Grid.Row="0" Grid.Column="0" Margin="2" ToolTip="Edit Database or Search Filter">
                                    <Menu.Background>
                                        <ImageBrush ImageSource="/FFXIMDCwpf1;component/Images/MainWeaponIcon.png" Stretch="Uniform" />
                                    </Menu.Background>
                                    <MenuItem Height="22" Width="44">
                                        <MenuItem Header="Edit Database" />
                                    </MenuItem>
                                </Menu>
                                <ComboBox Name="MainWeapon1" Grid.Row="0" Grid.Column="1"/>
                                <ComboBox Name="MainWeapon2" Grid.Row="0" Grid.Column="2"/>
                                <Menu Grid.Row="1" Grid.Column="0" Margin="2" ToolTip="Edit Database or Search Filter">
                                    <Menu.Background>
                                        <ImageBrush ImageSource="/FFXIMDCwpf1;component/Images/SubWeaponIcon.png" Stretch="Uniform" />
                                    </Menu.Background>
                                    <MenuItem Height="22" Width="44">
                                        <MenuItem Header="Edit Database" />
                                    </MenuItem>
                                </Menu>
                                <ComboBox Name="SubWeapon1" Grid.Row="1" Grid.Column="1"/>
                                <ComboBox Name="SubWeapon2" Grid.Row="1" Grid.Column="2"/>
                            </Grid>
                        </Expander>

    ... par contre dans le code behind :
    Code vb.net : 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
    Class MainWindow
        ' Instanciation des DataTables qui serviront de base aux DataViews
        Dim JobsList As New DataSet.JobsListDataTable
        Dim WeaponsList As New DataSet.WeaponDataTable
     
        ' Création des BindingCollectionView (supportant INotifyCollectionChanged et CustomFilter) qui serviront d'ItemsSource aux Comboboxs.
        ' Note: Ne pouvant pas directement utiliser GetDefaultView(Datatable) pour contruire les BindingCollectionView,
        ' il faut initialiser au préalable chaque BindingCollectionView avec son propre DataView, de façon à ce que les differentes vues soient filtrées indépendamment.
        Dim MainJobBindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(New DataView(JobsList)), BindingListCollectionView)
        Dim SubJobBindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(New DataView(JobsList)), BindingListCollectionView)
        Dim MainWeapon1BindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(New DataView(WeaponsList)), BindingListCollectionView)
        Dim SubWeapon1BindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(New DataView(WeaponsList)), BindingListCollectionView)
        Dim MainWeapon2BindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(New DataView(WeaponsList)), BindingListCollectionView)
        Dim SubWeapon2BindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(New DataView(WeaponsList)), BindingListCollectionView)
     
        ' Variable empêchant l'appel intempestif de la routine "UpdateCBXItemsSources"
        Private IsReady As Boolean = False
     
        Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles MyBase.Loaded
            'Chargez les données dans la table JobsList.
            Dim DataSetJobsListTableAdapter As WpfApplication1.DataSetTableAdapters.JobsListTableAdapter = New WpfApplication1.DataSetTableAdapters.JobsListTableAdapter()
            DataSetJobsListTableAdapter.Fill(JobsList)
            'Chargez les données dans la table Weapon.
            Dim DataSetWeaponTableAdapter As WpfApplication1.DataSetTableAdapters.WeaponTableAdapter = New WpfApplication1.DataSetTableAdapters.WeaponTableAdapter()
            DataSetWeaponTableAdapter.Fill(WeaponsList)
     
            ' Construction de la colonne "Description" pour chacune des DataTables Equipements
            ' Chaque enregistrement de cette colonne est une String concaténant chaque champ de la DataTable avec la valeur correspondante (non vide),
            ' et servira de contenu dynamique pour une infobulle sur chaque ComboBoxItem.
            BuildDescriptions() ' Hors-topic ici
     
            ' Affectation des Bindings correspondants à chaque ComboBox, chacune ayant sa propre vue pour permettre un filtrage indépendant.
            MainJob.DataContext = MainJobBindingList
            SubJob.DataContext = SubJobBindingList
            SubJob.SelectedValue = ""
            MainWeapon1.DataContext = MainWeapon1BindingList
            SubWeapon1.DataContext = SubWeapon1BindingList
            MainWeapon2.DataContext = MainWeapon2BindingList
            SubWeapon2.DataContext = SubWeapon2BindingList
     
            IsReady = True
        End Sub
     
        Private Sub UpdateCBXItemsSources(ByVal sender As Object, ByVal e As RoutedEventArgs)
            If IsReady Then
                IsReady = False
     
                Dim RowFilter As String = "( [Equippable Jobs] LIKE '*" & MainJob.SelectedValue &
                                          "*' OR [Equippable Jobs] = 'ALL' )" &
                                          " AND Level <= '" & MainLevel.Text & "'"
                Dim MainWeapon1Type As String = "Hand-to-Hand"
                Dim SubWeapon1Type As String = ""
                Dim MainWeapon2Type As String = "Hand-to-Hand"
                Dim SubWeapon2Type As String = ""
                Dim Ranged1Type As String = ""
                Dim Ranged2Type As String = ""
                Dim FightStyle1 As String = "Hand-to-Hand"
                Dim FightStyle2 As String = "Hand-to-Hand"
                If Not IsNothing(MainWeapon1.SelectedValue) Then
                    MainWeapon1Type = WeaponsList.FindByNames(MainWeapon1.SelectedValue).Type
                    FightStyle1 = SkillsList.FindBySkills(MainWeapon1Type).Style
                End If
                If Not IsNothing(SubWeapon1.SelectedValue) Then : SubWeapon1Type = WeaponsList.FindByNames(SubWeapon1.SelectedValue).Type
                End If
                If Not IsNothing(MainWeapon2.SelectedValue) Then
                    MainWeapon2Type = WeaponsList.FindByNames(MainWeapon2.SelectedValue).Type
                    FightStyle2 = SkillsList.FindBySkills(MainWeapon2Type).Style
                End If
                If Not IsNothing(SubWeapon2.SelectedValue) Then : SubWeapon2Type = WeaponsList.FindByNames(SubWeapon2.SelectedValue).Type
                End If
                If Not IsNothing(RangedWeapon1.SelectedValue) Then : Ranged1Type = RangedList.FindByNames(RangedWeapon1.SelectedValue).Type
                End If
                If Not IsNothing(RangedWeapon2.SelectedValue) Then : Ranged2Type = RangedList.FindByNames(RangedWeapon2.SelectedValue).Type
                End If
     
                Select Case sender.Name
     
                    Case "MainJob", "MainLevel"
                        If IsNumeric(MainLevel.Text) And MainLevel.Text.Length = 2 Then
                            If CUInt(MainLevel.Text) > MaxMainLevel Then ' Verifier si MainLevel <= 90
                                MainLevel.Text = MaxMainLevel.ToString
                            End If
                            If CUInt(SubLevel.Text) > Math.Floor(CUInt(MainLevel.Text) / 2) Then ' Verifier si SubLevel <= MainLevel/2
                                SubLevel.Text = Math.Floor(CUInt(MainLevel.Text) / 2).ToString
                            End If
                        ElseIf Not IsNumeric(MainLevel.Text) OrElse CUInt(MainLevel.Text) < 0 Then : MainLevel.Text = "01"
                        ElseIf Not MainLevel.IsFocused AndAlso MainLevel.Text.Length <= 1 Then
                            MainLevel.Text = "0" & MainLevel.Text
                        End If
     
                        ' Filtrer : SubJob, toutes les cbx equipements
     
                        SubJobBindingList.CustomFilter = "Jobs <>'" & MainJob.SelectedValue & "'"
     
                        MainWeapon1BindingList.CustomFilter = RowFilter & " AND Type <> 'Grips' AND Type <> 'Shield'" &
                                                              " AND NOT( Names = '" & Replace(SubWeapon1.SelectedValue, "'", "''") & "' AND Rare = 'True' )"
     
                        MainWeapon2BindingList.CustomFilter = RowFilter & " AND Type <> 'Grips' AND Type <> 'Shield'" &
                                                              " AND NOT( Names = '" & Replace(SubWeapon2.SelectedValue, "'", "''") & "' AND Rare = 'True' )"
     
                        SubWeapon1BindingList.CustomFilter = RowFilter &
                                                             " AND Type <> 'Hand-to-Hand' AND Type <> 'Great Axe' AND Type <> 'Great Katana' AND Type <> 'Great Sword' AND Type <> 'Polearm' AND Type <> 'Scythe' AND Type <> 'Staff'" &
                                                             " AND " & IIf(FightStyle1 = "Hand-to-Hand", "Names = ''", IIf(FightStyle1 = "1Handed", "Type <> 'Grips'", IIf(FightStyle1 = "2Handed", "Type <> 'Shield' AND Type <> 'Axe' AND Type <> 'Club' AND Type <> 'Dagger' AND Type <> 'Katana' AND Type <> 'Sword'", "Type <>''"))) &
                                                             " AND NOT( Names = '" & Replace(MainWeapon1.SelectedValue, "'", "''") & "' AND Rare = 'True' )"
     
                        SubWeapon2BindingList.CustomFilter = RowFilter &
                                                             " AND Type <> 'Hand-to-Hand' AND Type <> 'Great Axe' AND Type <> 'Great Katana' AND Type <> 'Great Sword' AND Type <> 'Polearm' AND Type <> 'Scythe' AND Type <> 'Staff'" &
                                                             " AND " & IIf(FightStyle2 = "Hand-to-Hand", "Names = ''", IIf(FightStyle2 = "1Handed", "Type <> 'Grips'", IIf(FightStyle2 = "2Handed", "Type <> 'Shield' AND Type <> 'Axe' AND Type <> 'Club' AND Type <> 'Dagger' AND Type <> 'Katana' AND Type <> 'Sword'", "Type <>''"))) &
                                                             " AND NOT( Names = '" & Replace(MainWeapon2.SelectedValue, "'", "''") & "' AND Rare = 'True' )"
                    Case "SubJob", "SubLevel"
                        If IsNumeric(SubLevel.Text) AndAlso SubLevel.Text.Length = 2 AndAlso CUInt(SubLevel.Text) > Math.Floor(CUInt(MainLevel.Text) / 2) Then ' Verifier si SubLevel <= MainLevel/2
                            SubLevel.Text = Math.Floor(CUInt(MainLevel.Text) / 2).ToString
                        ElseIf IsNothing(SubJob.SelectedValue) OrElse Not IsNumeric(SubLevel.Text) OrElse CUInt(SubLevel.Text) < 0 OrElse SubJob.SelectedValue = "" Then : SubLevel.Text = "00"
                        ElseIf Not SubLevel.IsFocused AndAlso SubLevel.Text.Length <= 1 Then
                            SubLevel.Text = "0" & SubLevel.Text
                        End If
                        ' Filtrer : MainJob, et JobAbilities1 & 2
                        MainJobBindingList.CustomFilter = "Jobs <>'" & SubJob.SelectedValue & "'"
     
                    Case "MainWeapon1"
                        ' Filtrer : SubWeapon1
                        SubWeapon1BindingList.CustomFilter = RowFilter &
                                                             " AND Type <> 'Hand-to-Hand' AND Type <> 'Great Axe' AND Type <> 'Great Katana' AND Type <> 'Great Sword' AND Type <> 'Polearm' AND Type <> 'Scythe' AND Type <> 'Staff'" &
                                                             " AND " & IIf(FightStyle1 = "Hand-to-Hand", "Names = ''", IIf(FightStyle1 = "1Handed", "Type <> 'Grips'", IIf(FightStyle1 = "2Handed", "Type <> 'Shield' AND Type <> 'Axe' AND Type <> 'Club' AND Type <> 'Dagger' AND Type <> 'Katana' AND Type <> 'Sword'", "Type <>''"))) &
                                                             " AND NOT( Names = '" & Replace(MainWeapon1.SelectedValue, "'", "''") & "' AND Rare = 'True' )"
     
                    Case "MainWeapon2"
                        ' Filtrer : SubWeapon2
                        SubWeapon2BindingList.CustomFilter = RowFilter &
                                                             " AND Type <> 'Hand-to-Hand' AND Type <> 'Great Axe' AND Type <> 'Great Katana' AND Type <> 'Great Sword' AND Type <> 'Polearm' AND Type <> 'Scythe' AND Type <> 'Staff'" &
                                                             " AND " & IIf(FightStyle2 = "Hand-to-Hand", "Names = ''", IIf(FightStyle2 = "1Handed", "Type <> 'Grips'", IIf(FightStyle2 = "2Handed", "Type <> 'Shield' AND Type <> 'Axe' AND Type <> 'Club' AND Type <> 'Dagger' AND Type <> 'Katana' AND Type <> 'Sword'", "Type <>''"))) &
                                                             " AND NOT( Names = '" & Replace(MainWeapon2.SelectedValue, "'", "''") & "' AND Rare = 'True' )"
     
                    Case "SubWeapon1"
                        ' Filtrer : MainWeapon1
                        MainWeapon1BindingList.CustomFilter = RowFilter & " AND Type <> 'Grips' AND Type <> 'Shield'" &
                                                              " AND NOT( Names = '" & Replace(SubWeapon1.SelectedValue, "'", "''") & "' AND Rare = 'True' )"
     
                    Case "SubWeapon2"
                        ' Filtrer : MainWeapon2
                        MainWeapon2BindingList.CustomFilter = RowFilter & " AND Type <> 'Grips' AND Type <> 'Shield'" &
                                                              " AND NOT( Names = '" & Replace(SubWeapon2.SelectedValue, "'", "''") & "' AND Rare = 'True' )"
                    Case Else
                End Select
                IsReady = True
            End If
        End Sub
     
        ' Petite fonction pour calcul intermédiaire pour certaines expressions de filtrage.
        Function CalculSkill(ByVal Skill As String) As Integer
            If Skill = "" Or Skill = "Grips" Or Skill = "Shield" Then : Return 0
            End If
     
            Dim SkillRank = StatSkillGrades.FindByStatsSkills(Skill).Item(MainJob.SelectedValue)
     
            If IsDBNull(SkillRank) Then
                If SubJob.SelectedValue <> "" Then
                    SkillRank = StatSkillGrades.FindByStatsSkills(Skill).Item(SubJob.SelectedValue)
                    If IsDBNull(SkillRank) Then : Return 0
                    End If
                Else : Return 0
                End If
            End If
            Return SkillCaps.FindByLevel(CShort(MainLevel.Text)).Item(SkillRank)
        End Function
    End Class

    Donc contrairement en WinForms où j'avais juste à remplir mes DataTables avec les .Fill(), en WPF apparemment VB2010 n'instancie rien...
    Pour rappel, mes Datatables sont issues d'une base de données Access, importées avec l'Assistant "Concepteur" de VB.

    Le trick ensuite était de pouvoir utiliser CustomFilter (cf. posts précédents), proprièté propre aux BindingListCollectionViews (et non pas CollectionView).
    D'où l'étape de "conversion" de mes DataTables en BindingListCollectionView, et dans la foulée duplication (vu que mes comboboxs sont indépendantes et par paires).
    En réalité j'ai + de 30 paires de comboboxs, d'où l'organisation des expressions de filtrage (les Strings CustomFilter) sous forme d'un Select Case géant. Note au passage: j'ai centralisé les expressions "communes" dans la variable "RowFilter" pour simplifier la lecture du code...

    Résultat: à chaque changement de valeur d'une des comboboxs "Master" (MainJob ou MainLevel ou SubJob ou SubLevel), les comboboxs dépendantes voient leurs ItemsSource updatées automatiquement.
    Encore mieux: si une valeur se trouvait dans une de ces comboboxs "Slaves" et que l'on change la valeur d'une combobox "Master", le CustomFilter la resetera à "" si cette valeur ne remplit pas les critères de filtrage... ou la laissera telle quelle si c'est "ok" ! (en WinForms, le filtrage resetait tout le temps à "" ...)

    Voilà si ca peut aider d'autres.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Linq to Entity] filtrage en cascade (dur dur)
    Par CUCARACHA dans le forum Linq
    Réponses: 8
    Dernier message: 20/09/2009, 21h19
  2. [WPF / XAML] Propriété topmost = true mais fenetre en arriére plan
    Par UNi[FR] dans le forum Windows Presentation Foundation
    Réponses: 4
    Dernier message: 16/01/2008, 14h32
  3. Réponses: 3
    Dernier message: 16/01/2008, 11h45
  4. [WPF-XAML] freeBrowser 1.0 - Système de skin
    Par GeffD dans le forum Windows Presentation Foundation
    Réponses: 25
    Dernier message: 30/01/2007, 15h54

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