2017-08-02 10 views
4

Je cherche à modifier un ListView WPF afin que les éléments soient rendus horizontalement, et il y a un séparateur entre le premier élément et tous les éléments suivants. Quelque chose comme ça: Horizontal list with first item separatedComment puis-je remplacer le ContentTemplate d'un ListView pour ajouter un séparateur vertical?

J'ai le bit horizontal, mais je suis coincé avec le séparateur. J'ai essayé d'utiliser un DataTemplate, mais le séparateur Intègre dans l'élément réel qui signifie qu'il est mise en surbrillance lorsque je passe la souris (notez que je utilise Caliburn, mais je ne pense pas que cela aura une incidence sur la question beaucoup):

<UserControl.Resources> 
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> 
</UserControl.Resources> 
<StackPanel Margin="20"> 
    <ListView Name="Items" BorderThickness="0"> 
     <ListView.ItemTemplate> 
      <DataTemplate> 
       <StackPanel Orientation="Horizontal"> 
        <ContentControl cal:View.Model="{Binding}" /> 
        <Border Name="Separator" Width="2" Margin="5,10" HorizontalAlignment="Center" Background="Red" Visibility="{Binding IsFirst, Converter={StaticResource BooleanToVisibilityConverter}}" /> 
       </StackPanel> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
     <ListView.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel Orientation="Horizontal" /> 
      </ItemsPanelTemplate> 
     </ListView.ItemsPanel> 
    </ListView> 
</StackPanel> 

Les articles sont vues très basiques avec cette frontière:

<Border Background="White" BorderBrush="Black" BorderThickness="2"> 

Comment ça regarde avec DataTemplate:

Incorrectly highlighting the selector

Après spendi ng le matin la lecture sur des modèles, j'ai décidé que ControlTemplate était la solution qui, après une lutte m'a donné ce code:

<UserControl.Resources> 
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> 
    <Style TargetType="ListViewItem"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="ListViewItem"> 
        <StackPanel Margin="10" Orientation="Horizontal"> 
         <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" /> 
         <Border Name="Separator" Width="2" Margin="5,10" HorizontalAlignment="Center" Background="Red" Visibility="{Binding IsFirst, Converter={StaticResource BooleanToVisibilityConverter}}" /> 
        </StackPanel> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</UserControl.Resources> 
<StackPanel> 
    <ListView Name="Items"> 
     <ListView.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel Orientation="Horizontal" /> 
      </ItemsPanelTemplate> 
     </ListView.ItemsPanel> 
    </ListView> 
</StackPanel> 

Cela semble presque identique, mais maintenant je suis incapable de mettre en évidence les éléments pour une raison quelconque. Je pensais que j'avais peut-être outrepassé les déclencheurs, et j'ai essayé d'ajouter une entrée ControlTemplate.Triggers basée sur cette réponse: Change selection-color of WPF ListViewItem pour ramener le comportement de mise en évidence, mais sans succès.

Comment puis-je obtenir le résultat que je recherche, et ControlTemplate est-il le bon endroit pour effectuer ce changement?

EDIT: Idéalement, je suis à la recherche d'une solution en utilisant simplement xaml.

+1

Ce séparateur fait plutôt partie du conteneur d'éléments que ListViewItem lui-même. Vous utilisez maintenant 'StackPanel' horizontal, essayez d'écrire' HorizontalPanelWithSeparator'. – Sinatr

+0

Je vais essayer, merci. – Jamey

Répondre

2

Voici une tentative rapide de panneau personnalisé avec séparateur

public class MyPanel : StackPanel 
{ 
    static MyPanel() 
    { 
     OrientationProperty.OverrideMetadata(typeof(MyPanel), new FrameworkPropertyMetadata(Orientation.Horizontal)); 
    } 

    protected override void OnRender(DrawingContext dc) 
    { 
     base.OnRender(dc); 
     if (Children.Count >= 2) 
     { 
      var child = Children[0] as FrameworkElement; 
      if (child != null) 
       dc.DrawLine(new Pen(Brushes.Red, 2), new Point(child.ActualWidth + 2, 5), new Point(child.ActualWidth + 2, ActualHeight - 5)); 
     } 
    } 
} 

utiliser comme ceci

<ListView.ItemsPanel> 
    <ItemsPanelTemplate> 
     <local:MyPanel/> 
    </ItemsPanelTemplate> 
</ListView.ItemsPanel> 

panneau Actuellement ne pas organiser/enfants de mesure d'allouer l'espace pour le séparateur, vous avez pour s'assurer qu'il y a une marge entre eux.

+0

Merci pour cela, avec un peu de tripoter les marges j'ai pu produire le comportement que je voulais. Idéalement, je suis à la recherche d'une solution xaml, donc je vais laisser la question ouverte et continuer à expérimenter, mais si rien d'autre ne vient, je vais accepter cela. – Jamey

0

Pour cela, utilisez ItemTemplateSelector.

Si vous pouvez montrer votre modèle de vue, je peux vous aider plus concrètement. Mais votre modèle de données pour le premier article sera différent du reste et contiendra le séparateur que vous voulez. Le reste des éléments peut utiliser le modèle normal.

En tant que solution de remplacement, créez une liaison entre la propriété de visibilité et un champ booléen dans votre modèle de vue, ce qui n'est vrai que pour le premier élément.

+0

Salut Tanveer, merci pour votre réponse, malheureusement la visibilité n'est pas mon problème. J'ai du mal à faire en sorte que le séparateur ne soit pas inclus dans la zone de surbrillance lorsque je passe la souris sur le premier élément (comme on peut le voir dans ma deuxième image). Comme pour les ViewModels, le 'ItemViewModel' a simplement une propriété' boolean IsFirst', et le 'ItemsViewModel' contient simplement une propriété' List 'que j'initialise dans le constructeur avec 3 items (passant vrai au premier et faux aux deux secondes). – Jamey

0

J'ai réussi à comprendre comment rajouter les déclencheurs (que j'ai confirmés manquaient en utilisant mon nouvel outil WPF favori WPF Inspector). Une fois que cela a été fait le dernier problème était que le séparateur déclenchait aussi une souris sur l'événement pour le premier élément que je fixe en ciblant la frontière intérieure:

<UserControl.Resources> 
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> 
    <Style TargetType="ListViewItem"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="ListViewItem"> 
        <StackPanel Orientation="Horizontal"> 
         <Border x:Name="ItemBorder" Padding="2"> 
          <StackPanel> 
           <ContentPresenter /> 
          </StackPanel> 
         </Border> 
         <Border Name="Separator" Width="2" Margin="5,10" HorizontalAlignment="Center" Background="Red" Visibility="{Binding IsFirst, Converter={StaticResource BooleanToVisibilityConverter}}" /> 
        </StackPanel> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsSelected" Value="True"> 
          <Setter TargetName="ItemBorder" Property="Border.Background" Value="Blue" /> 
          <Setter TargetName="ItemBorder" Property="Border.BorderBrush" Value="Green" /> 
         </Trigger> 
         <DataTrigger Binding="{Binding ElementName=ItemBorder, Path=IsMouseOver}" Value="True"> 
          <Setter TargetName="ItemBorder" Property="Border.Background" Value="Yellow" /> 
         </DataTrigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</UserControl.Resources> 
<StackPanel> 
    <ListView Name="Items"> 
     <ListView.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel Orientation="Horizontal" /> 
      </ItemsPanelTemplate> 
     </ListView.ItemsPanel> 
    </ListView> 
</StackPanel> 

Pour une raison inconnue, l'élément ItemBorder a besoin d'un rembourrage de 2 sinon, la frontière ne peut pas être vue.