2017-01-10 38 views
8

Mam ListBox gdzie doszło do grupowania w oparciu o właściwości jak ten:Vertical Separator w ListBox Grupa

CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(listbox.ItemsSource); 
PropertyGroupDescription groupDescription = new PropertyGroupDescription("CurrentDate"); 
view.GroupDescriptions.Add(groupDescription); 

A po grupowania chcę dodać pionowy separator pomiędzy grupami i napisałem kod jak to:

<ListBox.GroupStyle> 
    <GroupStyle> 
     <GroupStyle.HeaderTemplate> 
      <DataTemplate> 
       <StackPanel Orientation="Horizontal"> 
        <Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" /> 
        <TextBlock Text="{Binding Path=Name}" 
           FontWeight="Bold"/> 
       </StackPanel> 
      </DataTemplate> 
     </GroupStyle.HeaderTemplate> 
     <GroupStyle.Panel> 
      <ItemsPanelTemplate> 
       <VirtualizingStackPanel Orientation="Horizontal"/> 
      </ItemsPanelTemplate> 
     </GroupStyle.Panel> 
    </GroupStyle> 
</ListBox.GroupStyle> 

Ale to pojawia się tak:

enter image description here

Podczas gdy chcę, aby separator zejść całkowicie, ale gdy próbuję zwiększyć wysokość separatora, przedmioty idą w dół wraz z tym.

+0

Nie jestem ekspertem, ale czy nie powinieneś także dodać 'Separator' do' ItemsPanelTemplate'? –

+0

Proszę podać pełną XAML i kod. Łatwiej będzie go zwiększyć i znaleźć empiryczne rozwiązanie. – Kilazur

Odpowiedz

1

Nie mogę sobie wyobrazić, że to rozwiązanie jest gotowe do użycia, ponieważ próbujesz przestawić grupy. Zrobiłem przykład, ale nie mogę go zmienić rozmiar szerokość kolumn w itemsarea ale w nagłówku bez użycia separatory:

Code-Behind

public partial class Window1 { 

    public Window1() { 
     InitializeComponent(); 

     this._items.Add(new Item { Name = "one", DateTime = DateTime.Today }); 
     this._items.Add(new Item { Name = "two", DateTime = DateTime.Today.Subtract(new TimeSpan(1, 0, 0, 0)) }); 
     this._items.Add(new Item { Name = "three", DateTime = DateTime.Today.Subtract(new TimeSpan(1, 0, 0, 0)) }); 
     this._items.Add(new Item { Name = "four", DateTime = DateTime.Today.Add(new TimeSpan(1, 0, 0, 0)) }); 
     this._items.Add(new Item { Name = "five", DateTime = DateTime.Today.Add(new TimeSpan(1, 0, 0, 0)) }); 
     this.DataContext = this; 
    } 

    private ObservableCollection<Item> _items = new ObservableCollection<Item>(); 

    public ObservableCollection<Item> Items => _items; 

    } 


    public abstract class ViewModelBase : INotifyPropertyChanged { 
    public event PropertyChangedEventHandler PropertyChanged; 

    [NotifyPropertyChangedInvocator] 
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { 
     this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    } 

    public class Item : ViewModelBase { 
    private string _name; 
    private DateTime _dateTime; 

    public string Name { 
     get { 
     return this._name; 
     } 
     set { 
     if (value == this._name) 
      return; 
     this._name = value; 
     this.OnPropertyChanged(); 
     } 
    } 

    public DateTime DateTime { 
     get { 
     return this._dateTime; 
     } 
     set { 
     if (value.Equals(this._dateTime)) 
      return; 
     this._dateTime = value; 
     this.OnPropertyChanged(); 
     } 
    } 

    } 

Grupowanie z zasobów

<Window.Resources> 
     <CollectionViewSource x:Key="CollectionViewSource" Source="{Binding Items}"> 
      <CollectionViewSource.GroupDescriptions> 
       <PropertyGroupDescription PropertyName="DateTime" /> 
      </CollectionViewSource.GroupDescriptions> 
     </CollectionViewSource> 
    </Window.Resources> 

ListBox

<ListBox ItemsSource="{Binding Source={StaticResource CollectionViewSource}}" Width="400" Height="200"> 
      <ListBox.GroupStyle> 
       <GroupStyle> 
        <GroupStyle.HeaderTemplate> 
         <DataTemplate> 
          <GridViewColumnHeader Content="{Binding Name}"/> 
         </DataTemplate> 
        </GroupStyle.HeaderTemplate> 
        <GroupStyle.Panel > 
         <ItemsPanelTemplate> 
          <VirtualizingStackPanel Orientation="Horizontal"/> 
         </ItemsPanelTemplate> 
        </GroupStyle.Panel> 
       </GroupStyle> 
      </ListBox.GroupStyle> 
      <ListBox.ItemContainerStyle> 
       <Style TargetType="ListBoxItem"> 
        <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter> 
        <Setter Property="VerticalContentAlignment" Value="Stretch"></Setter> 
       </Style> 
      </ListBox.ItemContainerStyle> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <Border BorderBrush="DarkGray" BorderThickness="0,0,1,0" Margin="-6,-2,-6,-2"> 
         <StackPanel Margin="6,2,6,2"> 
          <TextBlock Text="{Binding Name}"/> 
         </StackPanel> 
        </Border> 

       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 

Najważniejszym elementem tego rozwiązania jest użycie GridViewColumnHeader jako nagłówka dla właściwości GroupStyle.

Prawdopodobnie lepszym rozwiązaniem może być zmiana ListBoxa na ListView i ustawienie ListView na View -Property na GridView. Wymaga to jednak zmiany struktury danych.

Uwaga

grupowanie ListBox nigdy nie miał do wykonania zadanie, które starają się zrobić. Domyślnym sposobem z listbox i grupowania jest mieć ekspandery w obszarze zawartości pola listy w sposób opisany here

6

Diagnoza

Gdy pozycje grupę, którą w ListBox wykorzystujące CollectionView + GroupStyle co się dzieje, jest ListBox wyświetla listę GroupItem kontroli , każdy reprezentujący grupę przedmiotów. A GroupItem zasadniczo składa się z ContentPresenter (do prezentacji nagłówka) i ItemsPresenter (do prezentacji zgrupowanych pozycji) umieszczonych w StackPanel.

Po określeniu GroupStyle.HeaderTemplate zostanie on użyty jako ContentTemplate dla wspomnianego ContentPresenter. Jeśli więc zwiększysz wysokość modelu Separator, nadal będzie on zawarty w ContentPresenter, powodując jego wzrost w pionie, a elementy będą nadal układane poniżej - stąd wynik.

Rozwiązanie

Co trzeba zrobić, aby osiągnąć swój cel jest ponowne szablonie GroupItem tak że Separator jest wyświetlany obok ContentPresenter i ItemsPresenter, a następnie podłączyć go za pomocą GroupStyle.ContainerStyle. Dla wygody, postawmy go w ListBox.Resources słownika:

<ListBox (...)> 
    <ListBox.Resources> 
     <ControlTemplate x:Key="GroupItemTemplate" TargetType="{x:Type GroupItem}"> 
      <DockPanel> 
       <Separator DockPanel.Dock="Left" 
          Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" /> 
       <StackPanel> 
        <ContentPresenter /><!-- This will be automatically wired --> 
        <ItemsPresenter Margin="5,0,0,0" /><!-- So will this --> 
       </StackPanel> 
      </DockPanel> 
     </ControlTemplate> 
    </ListBox.Resource> 
    <ListBox.GroupStyle> 
     <GroupStyle> 
      <GroupStyle.HeaderTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Path=Name}" FontWeight="Bold" /> 
       </DataTemplate> 
      </GroupStyle.HeaderTemplate> 
      <GroupStyle.ContainerStyle> 
       <Style TargetType="{x:Type GroupItem}"> 
        <Setter Property="Template" 
          Value="{StaticResource GroupItemTemplate}" /> 
       </Style> 
      </GroupStyle.ContainerStyle> 
      (...) 
     </GroupStyle> 
    </ListBox.GroupStyle> 
    (...) 
</ListBox> 

Zauważ, że usuwa się separator z szablonu nagłówka.

Oto możliwych wyników może chcesz uzyskać (kładę niebieskie obramowanie wokół ListBox odróżnić # 3 i # 4):

enter image description here

Wyciąg kod I, pod warunkiem wolę domyślnie daje # 1 (wszystkie separatory są rozciągnięte w pionie na całym obszarze ListBox).

Aby osiągnąć # 2 (separatory rozciągają się tylko do ostatniego elementu z odpowiedniej grupy), należy dodać <Setter Property="VerticalAlignment" Value="Top" /> do GroupStyle.ContainerStyle. Alternatywnie możesz umieścić go na szablonie DockPanel w szablonie GroupItem.

Aby uzyskać # 3 (separatory rozciągają się do wysokości największej grupy), należy dodać VerticalAlignment="Top" do panelu wewnątrz GroupStyle.Panel (w twoim przypadku).

I na konieC# 4 (sam numer ListBox jest ograniczony do wielkości największej grupy) można uzyskać, umieszczając VerticalAlignment="Top" na samym ListBox.