2012-06-16 1 views
1

Pour un projet, j'ai implémenté un petit contrôle similaire à IntelliSense qui n'est rien d'autre qu'un ListBox. Ses DataTemplate consistent en un StackPanel en tenant un Image et un TextBlock. Rien d'autre. Comme vous pouvez le voir dans la première capture d'écran de mon contrôle, la boîte de sélection de la zone de liste sélectionne l'élément entier (ce qui est généralement exactement ce que l'on pouvait s'y attendre):Redimensionner Boîte de sélection WPF ListBox

Custom ListBox

Cependant mes icônes « volées » de VS11 sont de faible qualité, donc je voulais régler la sélection comme Visual studio fait:

Visual Studio IntelliSense

Vous pouvez voir que seul le texte est sélectionné (la représentation visuelle n'ignore l'image/icône) et je veux savoir comment je peux implémenter ce comportement, aussi.

EDIT: Les icônes sont simplement des fichiers GIF avec un arrière-plan transparent. Je vais les remplacer par de meilleurs, mais néanmoins je suis intéressé par la façon d'obtenir le comportement désiré.

+0

Faites vos images ont un fond transparent? – Douglas

+0

GIFs transparents, yup. –

+0

Pourriez-vous changer l'arrière-plan du TextBlock au lieu de l'ensemble StackPanel? – benjer3

Répondre

3

est ici une solution en remplaçant le modèle de contrôle de ListBoxItem. Dans mon test, je viens d'afficher deux chaînes de texte, avec le second en surbrillance.

<Page.Resources> 
    <Style x:Key="ItemStyle" TargetType="ListBoxItem"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="ListBoxItem"> 
        <ContentPresenter/> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

    <Style x:Key="Selected" TargetType="{x:Type TextBlock}"> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding Path=IsSelected, 
         RelativeSource={RelativeSource Mode=FindAncestor, 
         AncestorType={x:Type ListBoxItem}}}" Value="True"> 
       <Setter Property="Background" 
         Value="{x:Static SystemColors.HighlightBrush}"/> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 

    <DataTemplate x:Key="ItemTemplate" DataType="{x:Type ViewModel:DataItem}"> 
     <Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="auto" SharedSizeGroup="c1"/> 
       <ColumnDefinition Width="auto" SharedSizeGroup="c2"/> 
       <ColumnDefinition Width="*"/> 
      </Grid.ColumnDefinitions> 
      <Image Source="../Images/Collapse.png"/> 
      <TextBlock Grid.Column="1" Text="{Binding Name}" Margin="0,0,5,0"/> 
      <TextBlock Style="{StaticResource Selected}" 
         Grid.Column="2" Text="{Binding Description}"/> 
     </Grid> 
    </DataTemplate> 
</Page.Resources> 

<Page.DataContext> 
    <Samples:Page3ViewModel/> 
</Page.DataContext> 

<Grid> 
    <ListBox 
     Grid.IsSharedSizeScope="True" 
     SelectedIndex="2" 
     HorizontalContentAlignment="Stretch" 
     ItemsSource="{Binding Items}" 
     ItemContainerStyle="{StaticResource ItemStyle}" 
     ItemTemplate="{StaticResource ItemTemplate}"/> 
</Grid> 

Le modèle de vue contient une collection d'éléments de données simples

public class Page3ViewModel 
{ 
    public Page3ViewModel() 
    { 
     Items = new List<DataItem> 
      { 
       new DataItem{Name = "One", Description = "First"}, 
       new DataItem{Name = "Two", Description = "Second"}, 
       new DataItem{Name = "Three", Description = "Third"}, 
       new DataItem{Name = "Four", Description = "Fourth"}, 
      }; 
    } 
    public IEnumerable<DataItem> Items { get; private set; } 
} 

Donner

enter image description here

+0

+ 1. C'est exactement ce que j'essayais de réaliser mais je ne pouvais pas le comprendre. Excellent travail. –

+0

+1. J'aime cette solution mais à mon avis, la solution @Benjamins (mise à jour) est un peu plus courte. Néanmoins, les deux font ce que je cherchais! –

1

Votre problème est dû à la manière dont WPF restitue chaque élément dans le ListBox. Il utilise un ItemContainerStyle qui enveloppe chaque élément dans un ListBoxItem. C'est ce ListBoxItem qui contient le contenu à afficher (dans votre cas, un StackPanel qui contient une Image et un TextBlock).

Par défaut, le ListBoxItem affiche le rectangle bleu autour tout le contenu qu'il affiche. J'ai trouvé une solution mais c'est un hack. Il suffit de rendre votre image plus grande et avoir la couleur de fond de pixel correspondent à la couleur de fond de la Listbox (dans mon cas, blanc) et utilisez le code XAML suivant.

<ListBox Margin="5" 
     ItemsSource="{Binding Items}"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <StackPanel Orientation="Horizontal" 
         Margin="-2,0,0,0"> 
       <Image Source="Save-icon.png" /> 
       <TextBlock Margin="5,8,0,0" 
          Text="{Binding}" /> 
      </StackPanel> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Ceci est le résultat:

enter image description here

Mise à jour

Je suis venu avec une modification qui en fait un peu moins d'un hack. Dans mon ItemTemplate J'ai entouré l'image avec Bordure qui utilise la liaison pour obtenir sa couleur de fond de son parent ListBox. (L'image n'a plus de bordure autour d'elle).

Mise à jour du XAML à ceci:

<ListBox Margin="5" 
     ItemsSource="{Binding Items}" 
     Background="LightSteelBlue"> 

    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <StackPanel Orientation="Horizontal" 
         Margin="-2,0,0,0"> 
       <Border Background="{Binding Path=Background, RelativeSource={RelativeSource AncestorType=ListBox}}" 
         Padding="10"> 
        <Image Source="Save-icon.png"/> 
       </Border> 
       <TextBlock Margin="5,8,0,0" 
          Text="{Binding}" /> 
      </StackPanel> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 

</ListBox> 

Ceci est le nouveau résultat:

enter image description here

Maintenant, tout ce que vous devez faire est de mettre à jour la couleur de fond de la ListBox et tout va s'ajuster automatiquement. PAR EXEMPLE.

<ListBox Margin="20" 
     ItemsSource="{Binding Items}" 
     Background="PeachPuff"> 

enter image description here

+0

Il ne colorie toujours pas l'arrière-plan de l'image – Paparazzi

+0

Ma réponse indique clairement que vous avez besoin de votre image pour que la couleur d'arrière-plan de l'image corresponde à celle de la ListBox. –

+0

Je pensais à ceci aussi mais c'est * gênant * d'être lié au BG de la ListBox bien que je ne sache pas et autre solution de contournement. Néanmoins, merci, mais je vais attendre de voir si quelqu'un d'autre a une autre solution; sinon, j'accepterai votre réponse et vous honorer pour vos efforts. –