2010-11-21 10 views
14

Nie mogę zrozumieć, co robię źle. Chcę grupować elementy w listView. W rezultacie chcę zobaczyć coś takiego:Grupowanie elementów MVVM w ListView

enter image description here

It'm użyciu MVVM wzór. To mój kod XAML.

<CollectionViewSource x:Key="EmploeeGroup"        
         Source="{Binding Path=AllEmploees}"> 
    <CollectionViewSource.GroupDescriptions> 
    <PropertyGroupDescription PropertyName="FirstName" /> 
    </CollectionViewSource.GroupDescriptions> 
</CollectionViewSource> 

<ListView AlternationCount="2" 
      DataContext="{StaticResource EmploeeGroup}" 
      ItemsSource="{Binding IsAsync=True}" Padding="0,0,0,10"> 
    <ListView.GroupStyle> 
    <GroupStyle> 
     <GroupStyle.ContainerStyle> 
     <Style TargetType="{x:Type GroupItem}"> 
      <Setter Property="Margin" Value="0,0,0,5"/> 
      <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type GroupItem}"> 
       <Expander IsExpanded="True" BorderBrush="#FFA4B97F" 
              BorderThickness="0,0,0,1"> 
        <Expander.Header> 
        <DockPanel> 
         <TextBlock FontWeight="Bold" 
           Text="Name: "/> 
         <TextBlock FontWeight="Bold" 
           Text="{Binding Path=FirstName}"/> 
        </DockPanel> 
        </Expander.Header> 
        <Expander.Content> 
        <ItemsPresenter /> 
        </Expander.Content> 
       </Expander> 
       </ControlTemplate> 
      </Setter.Value> 
      </Setter> 
     </Style> 
     </GroupStyle.ContainerStyle> 
    </GroupStyle> 
    </ListView.GroupStyle> 
    <ListView.View> 
    <GridView> 
     <GridViewColumn Width="150" 
         Header="FirstName" 
         DisplayMemberBinding="{Binding Path=FirstName}"/> 
     <GridViewColumn Width="150" 
         Header="LastName" 
         DisplayMemberBinding="{Binding Path=LastName}"/> 
    </GridView> 
    </ListView.View> 
</ListView> 

To moje EmploeeListViewModel.cs

public class EmploeeListViewModel: ViewModelBase 
{ 
    readonly EmploeeRepository _emploeeRepository; 

    private ObservableCollection<EmploeeViewModel> _allmpl; 
    public ObservableCollection<EmploeeViewModel> AllEmploees 
    { 
    get 
    { 
     if (_allmpl == null) 
     { 
     _allmpl = new ObservableCollection<EmploeeViewModel>(); 
     CreateAllEmploee(); 
     } 
     return _allmpl; 
    } 
    } 

    public EmploeeListViewModel(EmploeeRepository emploeeRepository) 
    { 
    if (emploeeRepository == null) 
     throw new ArgumentNullException("emploeeRepository"); 

    _emploeeRepository = emploeeRepository; 
    _emploeeRepository.EmploeeAdded += this.OnEmploeeAddedToRepository; 
    } 

private void CreateAllEmploee() 
{ 
    List<EmploeeViewModel> all = 
       (from emploee in _emploeeRepository.GetEmploees() 
       select new EmploeeViewModel(emploee)).ToList(); 
    foreach (EmploeeViewModel evm in all) 
    { 
    evm.PropertyChanged += this.OnEmploeeViewModelPropertyChanged; 
    AllEmploees.Add(evm); 
    } 
    this.AllEmploees.CollectionChanged += this.OnCollectionChanged; 
} 

//this.OnCollectionChanged; 
//this.OnEmploeeViewModelPropertyChanged; 
} 

EmploeeViewModel.cs

public class EmploeeViewModel : ViewModelBase 
{ 
    #region Fields 
    Emploee _emploee; 
    bool _isSelected; 
    #endregion 

    #region Constructor 
    public EmploeeViewModel(Emploee emploee) 
    { 
     if (emploee == null) 
     throw new ArgumentNullException("emploee"); 
     this._emploee = emploee; 
    } 
    #endregion 

    #region Emploee Properties 
    public bool IsSelected 
    { 
     get { return _isSelected; } 
     set 
     { 
     if (value == _isSelected) 
      return; 

     _isSelected = value; 
     base.OnPropertyChanged("IsSelected"); 
     } 
    } 

    public string FirstName 
    { 
     get { return _emploee.FirstName; } 
     set 
     { 
     if (value == _emploee.FirstName) 
      return; 
     _emploee.FirstName = value; 
     base.OnPropertyChanged("FirstName"); 
     } 
    } 

    public string LastName 
    { 
     get { return _emploee.LastName; } 
     set 
     { 
     if (value == _emploee.LastName) 
      return; 
     _emploee.LastName = value; 
     base.OnPropertyChanged("LastName"); 
     } 
    } 
    #endregion 
} 
  • Dlaczego nie mogę związać "FirstName" nieruchomości z Expander.Header TextBlock?
  • Dlaczego ja Rodzaj obiektu
    MS.Internal.Data.CollectionViewGroupInternal wewnątrz Expander.Header (gdybym napisał wewnątrz Expander.Header Text = "{Binding}")>?

Jak zmienić mój XAML lub kod .cs produkować these results?

Odpowiedz

20

Sam znalazłem odpowiedź na to pytanie.

Obiekt wysyłany do konwertera jest typu: MS.Internal.Data.CollectionViewGroupInternal.

Głównym powodem jest użycie "Nazwy" do wiązania danych nazw grup po prostu dlatego, że jest to właściwość w CollectionViewGroupInternal, która zawiera nazwę, którą ma bieżący "zbiór grup" (zgodnie z określonym opisem GroupDescription).

Nieważne Co to jest GropertyName w PropertyGroupDescription. Musisz zawsze użyć {Binding Path = Name} w kontenerze GroupStyle.

Musiałem zmienić tylko jeden ciąg w moim XAML.

Od:

<TextBlock FontWeight="Bold" Text="{Binding Path=FirstName}"/> 

Do:

<TextBlock FontWeight="Bold" Text="{Binding Path=Name}"/> 
+0

Zastanawiam się, jak to zrobić z wielu PropertyGroupDescriptions ... – Sven

+1

Jest to niezwykle bazar. Zauważyłem to tutaj w tym poście http://www.wpf-tutorial.com/listview-control/listview-grouping/ i pomyślałem, że to może być literówka. Dlaczego na ziemi powinno zawsze być "Nazwa", ale nie nazwa rzeczywistego wiązania !!! Zdrowie przyjacielu. – Mehrad

+1

"Nazwa" to nazwa właściwości, która zawiera zgrupowany przedmiot. Masz grupę przedmiotów, z których wszystkie mają FirstName, a właściwość "Name" zawiera tę wspólną wartość. Staje się to bardziej oczywiste, gdy grupujesz się na złożonym typie. –

Powiązane problemy