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;
        }
原文地址:https://www.cnblogs.com/lopengye/p/7215851.html