2010-11-21 4 views
14

Я не могу понять, что я делаю неправильно. Я хочу группировать элементы в listView. В результате я хочу увидеть что-то вроде этого:MVVM Группировка элементов в ListView

enter image description here

It'm с использованием MVVM картины. Это мой код 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> 

Это мой 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 
} 
  • Почему я не могу связать "ПгвЬЫат" свойства с Expander.Header TextBlock?
  • Почему я возражаю типа
    MS.Internal.Data.CollectionViewGroupInternal внутри Expander.Header (если я писал в Expander.Header Текст = "{Binding}")>?

Как следует изменить мой XAML или .cs код для получения these results?

ответ

20

Я нашел ответ на этот вопрос сам.

Объект, который отправляется в преобразователь, имеет тип: MS.Internal.Data.CollectionViewGroupInternal.

Основная причина заключается в том, чтобы использовать «Имя» для привязки имен групп просто потому, что это свойство в CollectionViewGroupInternal, которое содержит имя, которое имеет текущая «групповая коллекция» (в соответствии с указанным вами GroupDescription).

Не важно Что такое GropertyName в PropertyGroupDescription. Вы должны всегда использовать {Binding Path = Name} в контейнере GroupStyle.

Мне пришлось изменить только одну строку в моем XAML.

От:

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

To:

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

Интересно, как сделать это с помощью нескольких PropertyGroupDescriptions ... – Sven

+1

Это чрезвычайно базаром. Я заметил это здесь, в этом сообщении http://www.wpf-tutorial.com/listview-control/listview-grouping/, и думал, что это может быть опечатка. Почему на земле это всегда должно быть «Имя», но не имя фактического связывания !!! Приветственный помощник. – Mehrad

+1

«Имя» - это имя свойства, которое содержит элемент, с которым вы группировались. У вас есть группа элементов, все из которых имеют имя FirstName, а свойство «Name» содержит это общее значение. Это становится более очевидным, когда вы группируете сложный тип. –

Смежные вопросы