WPF ListView 使用GridView 带有Header 以及点击header排序 sort
ListView:
<ListView x:Name="lvFiles" VerticalAlignment="Stretch" Background="Transparent" Width="Auto" AllowDrop="{Binding IsAllowDrop}" Margin="20,0,20,30" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" ButtonBase.Click="ButtonBaseClickedHandler" ItemContainerStyle="{StaticResource ListViewItemStyle}" ItemsSource="{Binding ContentItemsView}" dnd:DragDropHelper.IsDragSource="True" local:FileViewStyle.SortDefaultStyle="{StaticResource NormalSortHeaderTemplate}" local:FileViewStyle.SortAscStyle="{StaticResource AscSortHeaderTemplate}" local:FileViewStyle.SortDescStyle="{StaticResource DescSortHeaderTemplate}"> <ListView.View> <GridView ColumnHeaderContainerStyle="{StaticResource GridViewColumnHeader}"> <GridViewColumn Header="{StaticResource IDS_NAME}" x:Name="nameColumn" HeaderStringFormat="Name" HeaderTemplate="{StaticResource NormalSortHeaderTemplate}" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}, Converter={StaticResource AutoListViewColumnWidthConverter}}"> <GridViewColumn.CellTemplate> <DataTemplate > <DockPanel> <Image x:Name="img" Width="20" Height="20" Source="{Binding Icon,Converter={StaticResource ImgPathToImageConverter}}" SnapsToDevicePixels="True" UseLayoutRounding="True" RenderTransformOrigin="0.5,0.5" Margin="0,0,5,0"></Image> <customControl:EnhancedTextBlock Text="{Binding Name}" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" /> </DockPanel> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn HeaderStringFormat="Type" HeaderTemplate="{StaticResource NormalSortHeaderTemplate}" Width="80" Header="{StaticResource IDS_TYPE}" local:RangeColumn.MinWidth="80"> <GridViewColumn.CellTemplate> <DataTemplate > <customControl:EnhancedTextBlock Text="{Binding Type}" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn HeaderStringFormat="Size" HeaderTemplate="{StaticResource NormalSortHeaderTemplate}" Width="80" Header="{StaticResource IDS_SIZE}" local:RangeColumn.MinWidth="80"> <GridViewColumn.CellTemplate> <DataTemplate > <customControl:EnhancedTextBlock Text="{Binding SizeStr}" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn HeaderStringFormat="Modified" HeaderTemplate="{StaticResource NormalSortHeaderTemplate}" Width="120" Header="{StaticResource IDS_MODIFIED}" local:RangeColumn.MinWidth="120"> <GridViewColumn.CellTemplate> <DataTemplate > <customControl:EnhancedTextBlock Text="{Binding LastModifyTimeString}" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> </GridView> </ListView.View> </ListView>
ListViewItemStyle:
<Style x:Key="ListViewItemStyle" TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource {x:Type ListViewItem}}"> <Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}" /> <Setter Property="IsSelected" Value="{Binding IsSelected}"/> <Setter Property="Height" Value="22" /> <EventSetter Event="RequestBringIntoView" Handler="ListViewItem_RequestBringIntoView"></EventSetter> <!--<Setter Property="helper:DragSelectionHelper.IsDragSelecting" Value="False"/>--> <!--<Style.Triggers> <Trigger Property="ListBoxItem.IsMouseOver" Value="True"> <Setter Property="helper:DragSelectionHelper.IsDragSelecting" Value="True" /> </Trigger> </Style.Triggers>--> </Style>
NormalSortHeaderTemplate:
<DataTemplate x:Key="NormalSortHeaderTemplate"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <customControl:EnhancedTextBlock Grid.Column="0" Text="{Binding}" VerticalAlignment="{TemplateBinding VerticalAlignment}" HorizontalAlignment="Left" FontWeight="{TemplateBinding TextBlock.FontWeight}" Foreground="{TemplateBinding TextBlock.Foreground}"/> </Grid> </DataTemplate>
AscSortHeaderTemplate:
<DataTemplate x:Key="AscSortHeaderTemplate"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <customControl:EnhancedTextBlock Grid.Column="0" Text="{Binding}" VerticalAlignment="{TemplateBinding VerticalAlignment}" FontWeight="{TemplateBinding TextBlock.FontWeight}" Foreground="{TemplateBinding TextBlock.Foreground}" /> <Path Grid.Column="1" x:Name="arrow" Margin="0,-6,6,0" VerticalAlignment="{TemplateBinding VerticalAlignment}" StrokeThickness="1" Fill="#FF4C4A4A" Data="M 5,10 L 15,10 L 10,5 L 5,10" /> </Grid> </DataTemplate>
DescSortHeaderTemplate:
<DataTemplate x:Key="DescSortHeaderTemplate"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <customControl:EnhancedTextBlock Grid.Column="0" Text="{Binding}" VerticalAlignment="{TemplateBinding VerticalAlignment}" FontWeight="{TemplateBinding TextBlock.FontWeight}" Foreground="{TemplateBinding TextBlock.Foreground}" /> <Path Grid.Column="1" x:Name="arrow" Margin="0,-6,6,0" VerticalAlignment="{TemplateBinding VerticalAlignment}" StrokeThickness="1" Fill="#FF4C4A4A" Data="M 5,5 L 10,10 L 15,5 L 5,5" /> </Grid> </DataTemplate>
GridViewColumnHeader:
<Style x:Key="GridViewColumnHeader" TargetType="{x:Type GridViewColumnHeader}"> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="VerticalAlignment" Value="Center"/> <Setter Property="Foreground" Value="#646464"/> <Setter Property="Background" Value="#f2f2f2" /> <Setter Property="Height" Value="22" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="GridViewColumnHeader"> <Grid Background="{TemplateBinding Background}"> <Border Name="HeaderBorder"> <ContentPresenter x:Name="HeaderContent" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" VerticalAlignment="Center" Margin="10,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ContentTemplate="{TemplateBinding ContentTemplate}"> </ContentPresenter> </Border> <Thumb x:Name="PART_HeaderGripper" HorizontalAlignment="Right" Style="{StaticResource GridViewColumnHeaderGripper}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
ButtonBaseClickedHandler:
#region sort /// <summary> /// last sort header /// </summary> GridViewColumnHeader _lastHeaderClicked = null; /// <summary> /// last sort direction /// </summary> ListSortDirection _lastDirection = ListSortDirection.Ascending; void ButtonBaseClickedHandler(object sender, RoutedEventArgs e) { #region sort try { GridViewColumnHeader headerClicked = e.OriginalSource as GridViewColumnHeader; ListSortDirection direction; if (headerClicked != null) { if (headerClicked.Column.HeaderStringFormat == null) return; string header = headerClicked.Column.HeaderStringFormat as string; if (headerClicked.Role != GridViewColumnHeaderRole.Padding) { if (headerClicked != _lastHeaderClicked) { direction = ListSortDirection.Descending; } else { if (_lastDirection == ListSortDirection.Ascending) { direction = ListSortDirection.Descending; } else { direction = ListSortDirection.Ascending; } } Sort(header, direction); if (direction == ListSortDirection.Ascending) { SetSortStyle(headerClicked.Column, true); } else { SetSortStyle(headerClicked.Column, false); } // Remove arrow from previously sorted header if (_lastHeaderClicked != null && _lastHeaderClicked != headerClicked) { //_lastHeaderClicked.Column.HeaderTemplate = null; _lastHeaderClicked.Column.HeaderTemplate = FileViewStyle.GetSortDefaultStyle(lvFiles); } _lastHeaderClicked = headerClicked; _lastDirection = direction; } } } catch (Exception ex) { Debug.WriteLine(ex); } #endregion } void SetSortStyle(GridViewColumn column, bool isAsc) { DataTemplate dataTemplate = null; if (isAsc) { dataTemplate = FileViewStyle.GetSortAscStyle(lvFiles); } else { dataTemplate = FileViewStyle.GetSortDescStyle(lvFiles); } if (dataTemplate != null) { column.HeaderTemplate = dataTemplate; } } void Sort(string sortBy, ListSortDirection direction) { if (string.IsNullOrEmpty(sortBy)) return; ICollectionView dataView = CollectionViewSource.GetDefaultView(lvFiles.ItemsSource); dataView.SortDescriptions.Clear(); SortDescription sortByType = new SortDescription("IsFolder", direction); dataView.SortDescriptions.Add(sortByType); SortDescription sortByProperty = new SortDescription(sortBy, direction); dataView.SortDescriptions.Add(sortByProperty); dataView.Refresh(); } #endregion
附上其他细节:
public FileManageListView() { InitializeComponent(); this.lvFiles.MouseDoubleClick += FilesView_MouseDoubleClick; lvFiles.KeyDown += LvFiles_KeyDown; lvFiles.SelectionChanged += LvFiles_SelectionChanged; } private void LvFiles_SelectionChanged(object sender, SelectionChangedEventArgs e) { foreach (var removedItem in e.RemovedItems.Cast<FileItemViewModel>()) { removedItem.IsSelected = false; } foreach (var addedItem in e.AddedItems.Cast<FileItemViewModel>()) { addedItem.IsSelected = true; } FileManagerViewModel.Instance.RaiseCanExecuteChanged(); }
private void Grid_DragOver(object sender, DragEventArgs e) { try { var itemViewModel = (sender as Grid).DataContext as FileItemViewModel; FileManagerViewModel.Instance.DragOverItem = itemViewModel; } catch (Exception ex) { Debug.WriteLine(ex); } } private void LvFiles_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Delete) { var deleteCommand = FileManagerViewModel.Instance.DeleteCommand as ICommand; if (deleteCommand.CanExecute(null)) { deleteCommand.Execute(null); } } } private void ListViewItem_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e) { e.Handled = true; }