2010-08-23 9 views
0

J'ai vu ICollectionView être introduit avec WPF pour gérer les situations où vous avez besoin de tri et de filtrage activé. J'ai même vu quelques articles qui trient des articles, mais ma principale préoccupation est de savoir pourquoi mon approche échoue. Voyons mon code:ICollectionView problème de tri dans ListView

<ListView ItemsSource="{Binding}" x:Name="lvItems" GridViewColumnHeader.Click="ListView_Click"> 
      <ListView.View> 
       <GridView AllowsColumnReorder="True"> 
        <GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}" /> 
        <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" /> 
        <GridViewColumn Header="Developer"> 
         <GridViewColumn.CellTemplate> 
          <DataTemplate> 
           <TextBlock Text="{Binding Path=Developer}" /> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 
        </GridViewColumn> 
        <GridViewColumn Header="Salary"> 
         <GridViewColumn.CellTemplate> 
          <DataTemplate> 
           <TextBlock Text="{Binding Path=Salary}" /> 
          </DataTemplate> 
         </GridViewColumn.CellTemplate> 
        </GridViewColumn> 

       </GridView> 
      </ListView.View> 
     </ListView> 

En codebehind, lorsque l'élément est cliqué que je fais comme ceci:

ICollectionView Source { get; set; } 


     private void ListView_Click(object sender, RoutedEventArgs e) 
     { 
      GridViewColumnHeader currentHeader = e.OriginalSource as GridViewColumnHeader; 
      if(currentHeader != null && currentHeader.Role != GridViewColumnHeaderRole.Padding) 
      { 
       //using (this.Source.DeferRefresh()) 
       //{ 
        SortDescription currentPropertySort = this.Source.SortDescriptions.FirstOrDefault<SortDescription>(item => item.PropertyName.Equals(currentHeader.Column.Header.ToString())); 
        if (currentPropertySort != null) 
        { 
         if (currentPropertySort.Direction == ListSortDirection.Ascending) 
          currentPropertySort.Direction = ListSortDirection.Descending; 
         else 
          currentPropertySort.Direction = ListSortDirection.Ascending; 

        } 
        else 
         this.Source.SortDescriptions.Add(new SortDescription(currentHeader.Column.Header.ToString(), ListSortDirection.Ascending)); 


       //} 
        this.Source.Refresh(); 
        this.lvItems.DataContext = this.Source; 
        this.lvItems.UpdateLayout(); 
      } 


     } 

Alors chaque fois que l'en-tête pour la zone de liste est cliqué, l'élément doivent être triés. Je maintiens la collection en utilisant une propriété appelée Source, puis en l'utilisant en appelant lvItems.DataContext = this.Source. Mais le code ne semble pas fonctionner.

Une aide? J'ai également téléchargé le code http://cid-bafa39a62a57009c.office.live.com/self.aspx/.Public/CollectionviewSourceSample.zip

+0

Pour tous les téléspectateurs de ce post, j'ai déjà implémenté cela. Si vous voulez voir jeter un oeil: http://www.abhisheksur.com/2010/08/woring-with-icollectionviewsource-in.html Merci – abhishek

Répondre

3

Voici une version mise à jour de votre méthode ListView_Click qui fonctionne un peu. Je ne suis pas sûr du comportement de tri que vous recherchez, mais la version ci-dessous "empile" un ensemble de descriptions de tri, faisant de la dernière colonne cliquée la "description de tri primaire". J'espère que cela a du sens et j'espère que le code ci-dessous aidera. =)

private void ListView_Click(object sender, RoutedEventArgs e) 
{ 
    GridViewColumnHeader currentHeader = e.OriginalSource as GridViewColumnHeader; 
    if(currentHeader != null && currentHeader.Role != GridViewColumnHeaderRole.Padding) 
    { 
     if (this.Source.SortDescriptions 
      .Count((item) => item.PropertyName.Equals(currentHeader.Column.Header.ToString())) > 0)     
     { 
      SortDescription currentPropertySort = this.Source 
       .SortDescriptions 
       .First<SortDescription>(item => item.PropertyName.Equals(currentHeader.Column.Header.ToString())); 

      //Toggle sort direction. 
      ListSortDirection direction = 
       (currentPropertySort.Direction == ListSortDirection.Ascending)? 
       ListSortDirection.Descending : ListSortDirection.Ascending; 

      //Remove existing sort 
      this.Source.SortDescriptions.Remove(currentPropertySort); 
      this.Source.SortDescriptions.Insert(0, new SortDescription(currentHeader.Column.Header.ToString(), direction)); 
     } 
     else 
     { 
      this.Source.SortDescriptions.Insert(0, new SortDescription(currentHeader.Column.Header.ToString(), ListSortDirection.Ascending)); 
     } 

     this.Source.Refresh(); 
    } 
} 

EDIT:

Par ailleurs, l'un des problèmes dans votre code ci-dessus est votre appel à "FirstOrDefault" pour interroger une SortDescription existante. Voir, SortDescription est une structure, qui est non-nullable de sorte que l'appel à FirstOrDefault ne sera jamais nul et retournera toujours une instance. Par conséquent, l'instruction "else" dans votre code ci-dessus ne sera jamais appelée.

+0

Wow c'est génial. J'ai juste négligé le type de SortDescription et donc plus de crédits pour vous pointer avec moi. Merci beaucoup pour votre code. – abhishek

+0

Dans mon cas, le ListView seulement a été trié à la première fois, et Refresh() ne fonctionne pas du tout! alors quel est le problème? – ARZ