2010-11-21 30 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 文本写道= “{结合}”)>?

我应该如何 改变我的XAML和.CS码产生 these results

回答

20

我自己找到了关于这个问题的答案。

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

主要原因是使用“名称”进行数据绑定组名仅仅是因为这是CollectionViewGroupInternal中包含当前“组集合”(根据您指定的GroupDescription)的名称的属性。

不重要什么是PropertyGroupDescription中的GropertyName。 你必须总是在GroupStyle容器中使用{Binding Path = Name}。

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

来源:

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

要:

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

我不知道如何与多个PropertyGroupDescriptions做到这一点... – Sven 2012-08-02 14:32:48

+1

这是非常集市。我在这篇文章http://www.wpf-tutorial.com/listview-control/listview-grouping/中注意到了这一点,并认为这可能是一个错字。为什么它应该始终是“名称”,但不是实际绑定的名称!队友的欢呼声。 – Mehrad 2015-01-16 06:50:55

+1

“名称”是保存您分组的项目的属性的名称。你有一组所有的项目共享一个名字,“名称”属性拥有该共同的价值。当你对一个复杂类型进行分组时,这会变得更加明显。 – 2016-11-29 23:13:46