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 :

Template d'un ToolTip Dynamique


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 Template d'un ToolTip Dynamique
    Bonjour

    Je cherche à mettre en forme une infobulle dynamique qui apparait lors du MouseOver d'un ComboboxItem, affichant des infos détaillées.
    Ces infos se trouvent dans la dernière colonne de la même BindingListCollectionView auquel la Combobox est bindée, et correspondent simplement à la concaténation des valeurs non-nulles de la DataRow correspondante.

    J'ai donc 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
    Class MainWindow
     
        Dim MainWeapon1BindingList As BindingListCollectionView = CType(CollectionViewSource.GetDefaultView(New DataView(WeaponsList)), BindingListCollectionView)
     
        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 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()
     
            MainWeapon1.DataContext = MainWeapon1BindingList
     
            IsReady = True
        End Sub
     
        ' Sub de remplissage de la colonne calculée "Description"
        ' Pour l'instant je ne l'ai implémentée que pour une seule Combobox, mais j'en ai d'autres qui attendent la même chose...
        Private Sub BuildDescriptions()
            WeaponsList.Columns.Add("Description")
     
            Dim Description As String
            With WeaponsList
                For Each DataRow In WeaponsList
                    Description = ""
                    If Not (DataRow.IsDamage_TypeNull OrElse _
                            DataRow.IsDelayNull OrElse _
                            DataRow.IsTypeNull OrElse _
                            DataRow.IsDMGNull) Then
                        Description = "[" & DataRow.Type & "] " & DataRow.Damage_Type & Chr(13)
                        Description += "DMG:" & DataRow.DMG & " Delay:" & DataRow.Delay & Chr(13)
                    End If
                    For i = 2 To .Columns.Count - 1 'Assuming columns are in correct order
                        If Not (IsDBNull(DataRow.Item(i)) OrElse .Columns(i).ColumnName.Equals("Names") OrElse _
                                                                 .Columns(i).ColumnName.Equals("DMG") OrElse _
                                                                 .Columns(i).ColumnName.Equals("Delay") OrElse _
                                                                 .Columns(i).ColumnName.Equals("Type") OrElse _
                                                                 .Columns(i).ColumnName.Equals("Damage Type") OrElse _
                                                                 .Columns(i).ColumnName.Equals("Level") OrElse _
                                                                 .Columns(i).ColumnName.Equals("Equippable Jobs") OrElse _
                                                                 .Columns(i).ColumnName.Contains("Notes") OrElse _
                                                                 .Columns(i).ColumnName.Equals("Rare")) Then
                            Description += .Columns(i).ColumnName & ": " & DataRow.Item(i) & " "
                        End If
                    Next
                    Description += Chr(13) & "Lvl" & DataRow.Level & " " & DataRow.Equippable_Jobs
                    DataRow.Item("Description") = Description
                Next
            End With
        End Sub
    End Class

    Puis dans le code XAML :
    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
                        <Expander Name="TPsets" Header="TP Sets" IsExpanded="True">
                            <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}"/>
                                        </Trigger>
                                    </Style.Triggers>
                                </Style>
                          <!--      <Style TargetType="ToolTip">
                                    <Setter Property="OverridesDefaultStyle" Value="True"/>
                                    <Setter Property="Template">
                                        <Setter.Value>
                                            <ControlTemplate TargetType="ToolTip">
                                                <DockPanel>
                                                    <Image DockPanel.Dock="Left"/>
                                                    <TextBlock DockPanel.Dock="Top" Text="{Binding Names}" TextAlignment="Left"/>
                                                    <TextBlock DockPanel.Dock="Bottom" Text="{Binding Description}" TextWrapping="Wrap"/>
                                                </DockPanel>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </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"/>
                            </Grid>
                        </Expander>

    et cela donne l'aperçu en 1ère pièce jointe.

    Le contenu de la Tooltip est bindé à la colonne "Description" prè-construite dans le Main_Loaded du code behind.
    Le style par défaut est sympa mais bon.... j'aurait préféré y rajouter le Nom de l'item en gras dans un autre textblock docké en haut, une image dockée contre la bordure gauche de la tooltip (dont je verrai la source + tard), et une icone booléenne dans le coin supérieur droit... cf. aperçu en 2e pièce jointe.
    ... et tant qu'on y est, le Placement de la Tooltip, bordure gauche dockée contre la bordure droite de la liste déroulante.
    Dans le code XAML ci-dessus, j'y ai mis en commentaire un "essai" de Template, mais il foire: le background de la tooltip semble devenu transparent et la police blanche (en regardant bien par-dessus la police noire des comboxitems qu'on arrive à voir cette drôle de Tooltip "invisible").

    J'ai essayé d'autres syntaxes mais j'avoue je m'y perds entre DataTemplate, ContentTemplate et Tooltip.Template, etc...
    Comment feriez-vous cela ?

    EDIT: J'ai trouvé pour le Placement, suffisait de rajouter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    <Setter Property="ToolTip" Value="{Binding Description}"/>
    <Setter Property="ToolTip.Placement" Value="Right"/>
    Images attachées Images attachées   

  2. #2
    Membre habitué
    Inscrit en
    Juin 2008
    Messages
    162
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 162
    Points : 172
    Points
    172
    Par défaut
    Salut

    En ce qui concerne le background c'est normal qu'il soit transparent car t'as redéfini le Template du ToolTip sans mettre de background à ton DockPanel. Et pour le Foreground du text il suffit de rajouter TextBlock.Foreground="Black" au dockPanel.

  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
    Donc si je comprends bien, le fait d'écrire Overrides DefaultStyle signifie tout mettre à 0 ? (d'où le Background/Foreground et Police à NULL ?)

    Ce que je souhaite c'est juste "compléter" la tooltip montrée en 1ere capture d'ecran. Autrement dit réutiliser ce qu'elle avait déjà puis rajouter des conteneurs pour mieux agencer son contenu...

    Dans le cours de M. Lasserre il écrit qu'il faut utiliser Overrides DefaultStyle sinon rien ne marchera... Ou j'ai mal compris ?

    Suis-je coincé et obligé de retemplater mes tooltip depuis 0 ? (tiens je vais essayer BasedOn=DefaultStyle pour voir...)

    EDIT: mettre BasedOn="{StaticResource {x:Type ToolTip}}" ou supprimer le Setter OverridesDefaultStyle remet la police par défaut noire. Mais le background reste transparent...
    Comment "récupérer" le Background par défaut des ToolTips de VB2010 ? en fait je veux dire carrément tout le style par défaut (car je vois qu'il y a aussi un dégradé et une ombre).

  4. #4
    Membre habitué
    Inscrit en
    Juin 2008
    Messages
    162
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 162
    Points : 172
    Points
    172
    Par défaut
    En fait le soucis n'est pas de redéfinir le style mais redefinir le ControlTemplate. Car c'est dans le template qu'on dit que le ToolTip est un Border avec une telle couleur contenant un ContentPresenter...
    Toi ce que tu essayes de faire c'est de mettre en forme le contenu du ToolTip donc c'est le contenu que tu doit formater:

    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
     
    <Style TargetType="ComboBoxItem">
                                    <Style.Triggers>
                                        <Trigger Property="IsMouseOver" Value="True">
                                            <Setter Property="ToolTip">
                                            <Setter.Value>
                                             <DockPanel>
                                                    <Image DockPanel.Dock="Left"/>
                                                    <TextBlock DockPanel.Dock="Top" Text="{Binding Names}" TextAlignment="Left"/>
                                                    <TextBlock DockPanel.Dock="Bottom" Text="{Binding Description}" TextWrapping="Wrap"/>
                                                </DockPanel>
                                            </Setter.Value>
                                            </Setter>
                                        </Trigger>
                                    </Style.Triggers>
                                </Style>

  5. #5
    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
    Citation Envoyé par goast Voir le message
    ...Toi ce que tu essayes de faire c'est de mettre en forme le contenu du ToolTip donc c'est le contenu que tu doit formater:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                                                 <DockPanel>
                                                    <Image DockPanel.Dock="Left"/>
                                                    <TextBlock DockPanel.Dock="Top" Text="{Binding Names}" TextAlignment="Left"/>
                                                    <TextBlock DockPanel.Dock="Bottom" Text="{Binding Description}" TextWrapping="Wrap"/>
                                                </DockPanel>
    Si je comprends bien, je dois mettre la portion de code ci-dessus dans un <ToolTip.ContentTemplate> inséré je ne sait où ?

    EDIT: je viens de tester ton code "tel quel", ca marche ! A force e chercher à tout comprendre, je pige de travers, Mea Culpa, Merci !

  6. #6
    Membre habitué
    Inscrit en
    Juin 2008
    Messages
    162
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 162
    Points : 172
    Points
    172
    Par défaut
    Je pensais le mettre directement dans le contenu du ToolTip telle que je l'ai mis dans le post d'avant mais effectivement un ToolTip est un ContentControl donc il a un ContentTemplate. Et donc dans le style du ToolTip tu peux changer le ContentTemplate.

    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
     
                                <Style TargetType="ToolTip">
                                    <Setter Property="ContentTemplate">
                                        <Setter.Value>
                                            <DataTemplate>
                                                <DockPanel>
                                                    <Image DockPanel.Dock="Left"/>
                                                    <TextBlock DockPanel.Dock="Top" Text="{Binding Names}" TextAlignment="Left"/>
                                                    <TextBlock DockPanel.Dock="Bottom" Text="{Binding Description}" TextWrapping="Wrap"/>
                                                </DockPanel>
                                            </DataTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </Style>

  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
    Ok pas de prob jusque là mais now j'ai 2 nouvo problemes :

    1. l'infobulle apparait que sur les comboboxitems, mais pas sur le mouseover de la combobox elle-même (liste déroulante fermée). j'ai essayé en copiant tout le style fait dans les posts précédents mais avec TargetType="Combobox", ca fait qu'une infobulle vide... Combobox.SelectionBox marche pas non plus...

    2. j'essaie de mettre un trigger pour une textblock a l'interieur de la tooltip avec ce code :
    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
                                <Style TargetType="ComboBoxItem">
                                    <Style.Triggers>
                                        <Trigger Property="IsMouseOver" Value="True">
                                            <Setter Property="ToolTip.Placement" Value="Right"/>
                                            <Setter Property="ToolTip">
                                                <Setter.Value>
                                                    <DockPanel Width="150">
                                                        <Image DockPanel.Dock="Left"/>
                                                        <StackPanel DockPanel.Dock="Top">
                                                            <DockPanel>
                                                                <TextBlock Text="{Binding Names}" DockPanel.Dock="Left" TextAlignment="Left" FontSize="14" FontWeight="Bold"/>
                                                                <TextBlock Name="Rarity" DockPanel.Dock="Right" TextAlignment="Right"/>
                                                            </DockPanel>
                                                            <TextBlock Text="{Binding Description}" TextWrapping="Wrap"/>
                                                        </StackPanel>
                                                    </DockPanel>
                                                </Setter.Value>
                                            </Setter>
                               <!--        <Setter Property="ToolTip.Triggers">
                                                <Setter.Value>
                                                    <DataTrigger Binding="{Binding Rare}">
                                                        <DataTrigger.Value>True</DataTrigger.Value>
                                                        <Setter TargetName="Rarity" Property="Text" Value="Rare"/>
                                                    </DataTrigger>                                         
                                                </Setter.Value>
                                            </Setter> -->
                                        </Trigger>
                                    </Style.Triggers>
                                </Style>
    cf. a la fin
    VB n'arrete pas de me souligner quequechose en bleu.... j'arrive pas a trouver une syntaxe logique et correcte.

  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
    Pendant mes recherches, on dirait que la zone de selection d'un combobox n'est pas considérée comme un un objet ComboboxItem. Resultat: le style ci-dessus etant défini pour le MouseOver d'un ComboboxItem, cela produit une ToolTip VIDE au-dessus du SelectedItem.
    En revanche, ce que je comprends pas, c'est que le MouseOver de la zone de selection produise a la base une ToolTip, le prog aurait du lever une exception ou RIEN afficher du tout...

    Une possible solution logique que je cherche toujours serait de trouver l'objet parent commun aux Comboboxitems + SelectedItem. Pour l'instant, j'ai trouvé ItemsContainerGenerator, ContentTemplate, et ItemsTemplate, mais soit ils n'ont pas la propriètè IsMouseOver, soit ne veulent pas faire l'objet du TargetType du <Style/>...

    Une autre est le ToolTipService mais là j'ai rien compris...

    Je viens de trouver un bug avec la syntaxe qui a priori marche bien, des posts précédents:
    si j'ai rien de selectionné et que je survol un comboboxitem, pas de probleme la tooltip s'affiche avec son contenu.
    Par contre si je selectionne un item puis survol encore les items de la listes déroulantes, là une exception est levée...
    L'élément spécifié est déjà l'enfant logique d'un autre élément. Déconnectez-le d'abord.

    Bon... pour simplifier la formulation du problème, j'ai le DataTemplate suivant :
    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
                                <DataTemplate x:Key="ToolTipContent">
                                    <DockPanel Width="150">
                                        <Image DockPanel.Dock="Left"/>
                                        <StackPanel DockPanel.Dock="Top">
                                            <DockPanel>
                                                <TextBlock Text="{Binding Names}" DockPanel.Dock="Left" TextAlignment="Left" FontSize="14" FontWeight="Bold"/>
                                                <TextBlock Name="Rarity" DockPanel.Dock="Right" TextAlignment="Right"/>
                                            </DockPanel>
                                            <TextBlock Text="{Binding Description}" TextWrapping="Wrap"/>
                                        </StackPanel>
                                    </DockPanel>
                                    <DataTemplate.Triggers>
                                        <DataTrigger Binding="{Binding Rare}">
                                            <DataTrigger.Value>True</DataTrigger.Value>
                                            <Setter TargetName="Rarity" Property="Text" Value="Rare"/>
                                        </DataTrigger>
                                    </DataTemplate.Triggers>
                                </DataTemplate>
    ... et dans les ressources <Style TargetType="ComboBox">...</Style>

    Question: Comment je fait pour affecter le DataTemplate pour qu'il fonctionne sur le survol aussi bien d'un comboboxitem que le SelectedItem ?

  9. #9
    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... peut-être que mes explications sont pas assez claires, je vais donc donner un autre exemple dans le même ordre d'idée:

    J'ai une combobox correctement bindée à une BindingListCollectionView filtrée. Une DataRow ressemble donc à:


    Ce que j'essaie de faire est d'afficher une info-bulle comme ceci (image PhotoShoppée):

    Avec bien sûr pas d'affichage d'info-bulle si le SelectedItem est NULL.

    Les 2 principaux problèmes que je rencontre sont:

    - je me prends l'exception "L'élément spécifié est déjà l'enfant logique d'un autre élément" si j'affecte une tooltip (dont le datatemplate est en resources)
    A LA FOIS au SelectedItem ET aux ComboBoxItems. Suffit de selectionner un item puis de revenir dans la liste déroulante: dès que la souris survole un comboBoxitem, l'exception est levée.

    - a cause des champs à valeur NULL de la bindinglistcollectionview, j'essaie de générer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <TextBlock Text="{Binding FieldHeader}"/><TextBlock Text=":"/><TextBlock Text="{Binding DataRow.FieldValue}"/>
    uniquement si FieldValue différent de NULL. Je n'ai pas réussi avec des datatrigger et encore moins de rendre la chose dynamique...

    Question: Comment dois-je implémenter ca ? XAML ou Code-Behind (ou mix des 2) ?

Discussions similaires

  1. Template variadique sur vecteur dynamique
    Par PilloBuenaGente dans le forum Langage
    Réponses: 8
    Dernier message: 05/08/2013, 18h04
  2. [Débutant] Tooltip dynamique sur un Textblock
    Par Towandaa dans le forum Windows Presentation Foundation
    Réponses: 3
    Dernier message: 11/10/2012, 11h41
  3. Tooltip dynamique d'image
    Par Norin dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 08/02/2012, 19h15
  4. Réponses: 10
    Dernier message: 13/04/2009, 13h02
  5. Pb Tooltip dynamique
    Par Mozofeuk dans le forum Silverlight
    Réponses: 3
    Dernier message: 03/04/2009, 11h38

Partager

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