MVVM Группировка элементов в ListView - PullRequest
16 голосов
/ 21 ноября 2010

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

enter image description here

Используется шаблон 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
}
  • Почему я не могу связать свойство "FirstName" с Expander.Header TextBlock?
  • Почему у меня тип объекта
    MS.Internal.Data.CollectionViewGroupInternal внутри Expander.Header (если я написал внутри Expander.Header Text = "{Binding}")>?

Как мне изменить свой код XAML или .CS, чтобы получить эти результаты ?

1 Ответ

22 голосов
/ 21 ноября 2010

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

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

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

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

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

От:

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

Кому:

<TextBlock FontWeight="Bold" Text="{Binding Path=Name}"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...