ListView中的MVVM分组项

Leo*_*nid 16 c# wpf listview mvvm

我无法理解我做错了什么.我想在listView中对项目进行分组.结果我希望看到类似的东西:

在此输入图像描述

它使用的是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>
Run Code Online (Sandbox Code Playgroud)

这是我的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;
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)
  • 为什么我不能将"FirstName"属性与Expander.Header TextBlock绑定?
  • 为什么我
    在Expander.Header中对象类型MS.Internal.Data.CollectionViewGroupInternal(如果我写在Expander.Header Text ="{Binding}")>?

我应该如何更改我的XAML或.CS代码以产生 这些结果

Leo*_*nid 22

我自己找到了这个问题的答案.

发送到转换器的对象的类型为:MS.Internal.Data.CollectionViewGroupInternal.

主要原因是使用"Name"进行数据绑定组名称只是因为它是CollectionViewGroupInternal中包含当前"组集合"所具有的名称的属性(根据您指定的GroupDescription).

不重要什么是PropertyGroupDescription中的GropertyName.您必须始终在GroupStyle容器中使用{Binding Path = Name}.

我不得不在我的XAML中只更改一个字符串.

从:

<TextBlock FontWeight="Bold" Text="{Binding Path=FirstName}"/>
Run Code Online (Sandbox Code Playgroud)

至:

<TextBlock FontWeight="Bold" Text="{Binding Path=Name}"/>
Run Code Online (Sandbox Code Playgroud)

  • “名称”是保存您分组的项目的属性的名称。您有一组项目,所有项目都共享一个 FirstName,并且“Name”属性保存该共同值。当您对复杂类型进行分组时,这一点变得更加明显。 (2认同)