2016-10-24 8 views
0

Ich habe ItemsControl mit bindefähiger Objektquelle und benutzerdefinierter Datentabelle für jedes Element. Die Elemente sind durch eine Linie getrennt. Aber letzter Punkt hat auch Trennzeichen, und das ist mein Problem, wie man die Linie für das letzte Element nicht rendert. Ich habe diese Lösung gefunden, aber es funktioniert in WPF:Zeilentrennzeichen in DataTemplate für ListView

How can a separator be added between items in an ItemsControl

EDIT: Hier ist meine Vorlage:

<ItemsControl Grid.Row="1" ItemsSource="{x:Bind ViewModel.AvailableStatuses}" x:Name="Statuses"> 
        <ItemsControl.ItemsPanel> 
         <ItemsPanelTemplate> 
          <StackPanel Orientation="Vertical" Padding="60,0,60,12"/> 
         </ItemsPanelTemplate> 
        </ItemsControl.ItemsPanel> 
        <ItemsControl.ItemTemplate> 
         <DataTemplate> 
          <Grid Background="Transparent"> 
           <Grid.RowDefinitions> 
            <RowDefinition Height="Auto"/> 
            <RowDefinition Height="*"/> 
           </Grid.RowDefinitions> 
           <i:Interaction.Behaviors> 
            <core:EventTriggerBehavior EventName="Tapped"> 
             <core:InvokeCommandAction Command="{Binding ElementName=ContentGrid, Path=DataContext.ChangeStatusCommand}" CommandParameter="{Binding}"/> 
            </core:EventTriggerBehavior> 
           </i:Interaction.Behaviors> 
           <Rectangle StrokeThickness="0.4" Height="0.4" x:Name="Separator" 
            VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Stroke="#D1D3D4" /> 
           <StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Stretch"> 
            <Image Source="{Binding Converter={StaticResource SelectContactStatusConverter}}" Margin="0,8,12,8"/> 
            <TextBlock Text="{Binding Converter={StaticResource EnumContactStatusToTextConverter}}" FontSize="20" VerticalAlignment="Center" Foreground="Black"/> 
           </StackPanel> 
          </Grid> 
         </DataTemplate> 
        </ItemsControl.ItemTemplate> 
       </ItemsControl> 

Antwort

0

Vielleicht ist es besser, den seperator oben zu setzen, weil das wird einfacher zu erkennen sein, anstatt das letzte Element zu kennen. Wenn Sie es oben platzieren, wird für das erste Element 1 Zeile zu viel angezeigt. Um dies zu beheben, fügen Sie eine Bindung für die Sichtbarkeitseigenschaft des Seperators mithilfe eines Konverters hinzu. Sie übergeben den Item-Index und wenn der Item-Index 1 ist, verstecken Sie den Seperator, andernfalls zeigen Sie ihn an.

Um den Index eines Elements zu erhalten, sehen Sie ein Beispiel hier: http://www.bendewey.com/index.php/523/alternating-row-color-in-windows-store-listview

+0

Das ist eine gute Lösung. Aber ItemsControl hat keine Indexeigenschaft – JuP

+0

Sie sprechen von einem ListView? In der PrepareContainerForItemOverride-Methode müssen Sie nur die IndexFromContainer-Methode aufrufen, um den Index für das aktuelle Element zu erhalten ... wenn es kein ListView ist, fügen Sie bitte einen Code/Xaml hinzu, damit wir sehen und nicht annehmen können .... – Depechie

+0

I ' Ich spreche über ItemsControl – JuP

0

gibt es wahrscheinlich ein paar verschiedene Möglichkeiten, dies zu tun, hier ist mein nehmen.

Stil Ihre Listview Stück Container mit dem Rand Pinsel und Dicke Sie haben wollen, und abonnieren Sie den ContainerContentChanging Veranstaltung:

<ListView ContainerContentChanging="ListView_ContainerContentChanging"> 
    <ListView.ItemContainerStyle> 
     <Style TargetType="ListViewItem"> 
      <Setter Property="BorderBrush" Value="Black"/> 
      <Setter Property="BorderThickness" Value="0,1,0,0"/> 
     </Style> 
    </ListView.ItemContainerStyle> 

    <x:String>1</x:String> 
    <x:String>2</x:String> 
    <x:String>3</x:String> 
    <x:String>4</x:String> 
</ListView> 

In Ihrem Code hinter:

private void ListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) 
{ 
    if (args.InRecycleQueue) 
    { 
     // Item is being recycled, make sure first item has no border 
     if (args.ItemIndex == 0) 
     { 
      var first = (ListViewItem)sender.ContainerFromIndex(0); 
      if (first != null) 
      { 
       first.BorderThickness = new Thickness(0); 
      } 
     } 
    } 
    else if (args.ItemIndex == 0) 
    { 
     // A new first item 
     ((ListViewItem)args.ItemContainer).BorderThickness = new Thickness(0); 

     var second = (ListViewItem)sender.ContainerFromIndex(1); 
     if (second != null) 
     { 
      second.ClearValue(BorderThicknessProperty); 
     } 
    } 
    else 
    { 
     // A new internal item 
     ((ListViewItem)args.ItemContainer).ClearValue(BorderThicknessProperty); 
    } 
} 

ich auf diese entschieden Ansatz aus ein paar Gründen:

  • Es ist sinnvoll, den Rahmenstil zu verwenden das ListViewItem anstelle von ItemTemplate, da es für alle Elemente in der Liste gleich ist, unabhängig davon, welche Elementvorlage für ein bestimmtes Element verwendet wird. Außerdem wird sichergestellt, dass die Linie den linken und rechten Rand des ListViews berührt.
  • Das visuelle Erscheinungsbild der Separatoren kann in XAML angepasst werden. Der Code-Behind kann in ein Verhalten (oder eine Unterklasse der ListView) eingefügt werden, wenn Sie ihn wiederverwenden möchten.
  • Es behält das korrekte Aussehen auch dann bei, wenn Elemente der Liste hinzugefügt/entfernt werden oder wenn Elemente neu geordnet werden.
  • Es funktioniert ordnungsgemäß mit UI-Virtualisierung.
  • Sie ist unabhängig von den an die Listenansicht gebundenen Daten.

Screenshot


EDIT

Es sieht aus wie Sie ein Item gemeint, nicht einen Listview. Wenn dies der Fall ist, müssen Sie etwas in Depechies Antwort tun, da ItemsControl nicht das ContainerContentChanging-Ereignis hat (Unterklasse ItemsControl und stattdessen PrepareContainerForItemOverride überschreiben), aber dies funktioniert wahrscheinlich nicht für dynamische Listen mit Elementen, die hinzugefügt und entfernt werden Laufzeit. Sie müssen mit verschiedenen Lösungen experimentieren, wenn dies für Sie wichtig ist.

0

ich mein Problem auf diese Weise gelöst:

private void Statuses_OnLoaded(object sender, RoutedEventArgs e) 
    { 
     var s = (ItemsControl) sender; 
     var container = s.ContainerFromIndex(0); 
     var element = container.FindChildren<Rectangle>("Separator"); 
     element.Visibility = Visibility.Collapsed; 
    } 

Was denken Sie?

Verwandte Themen