Visual Studio / WPF > event > e.OriginalSourceの使用

```txt:動作環境
Windows 7 Pro (32bit)
Microsoft Visual Studio 2017 Community
Sublime Text 2
```

http://gushwell.ldblog.jp/archives/52306698.html
を元に学習中。

```MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
//
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace _170605_t1450_collectionViewSource
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            _viewSource = listView1.ItemsSource as ICollectionView;
        }

        private GridViewColumnHeader _lastHeaderClicked = null;
        private ListSortDirection _lastDirection = ListSortDirection.Ascending;
        private ICollectionView _viewSource;

        private void GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e)
        {
            GridViewColumnHeader clickedHeader = e.OriginalSource as GridViewColumnHeader;
            if (clickedHeader == null)
            {
                return;
            }
            if (clickedHeader.Role != GridViewColumnHeaderRole.Padding)
            {
                ListSortDirection direction = ListSortDirection.Ascending;
                if (clickedHeader == _lastHeaderClicked &&
                    _lastDirection == ListSortDirection.Ascending)
                {
                    direction = ListSortDirection.Descending;
                }
                string header = (clickedHeader.Column.DisplayMemberBinding as Binding).Path.Path;
                Sort(header, direction);
                _lastHeaderClicked = clickedHeader;
                _lastDirection = direction;
            }
        }

        private void Sort(string sortBy, ListSortDirection direciton)
        {
            SortDescription sd = new SortDescription(sortBy, direciton);
            _viewSource.SortDescriptions.Clear();
            _viewSource.SortDescriptions.Add(sd);
            _viewSource.Refresh();
        }
    }

    public class Book
    {
        public string Title { get; set; }
        public string Author { get; set; }
        public double Price { get; set; }
        public DateTime Date { get; set; }
    }

    public class BooksData
    {
        public BooksData()
        {
            BookList = new ObservableCollection<Book>();
            BookList.Add(new Book
            {
                Title = "リファクタリング",
                Author = "Martin Fowler",
                Date = new DateTime(2000, 5, 1),
                Price = 5040,
            });
            BookList.Add(new Book
            {
                Title = "アジャイルプラクティス",
                Author = "Venkat Subramaniam",
                Date = new DateTime(2007, 12, 22),
                Price = 2520,
            });
            BookList.Add(new Book
            {
                Title = "詳細 正規表現",
                Author = "Jeffrey Friedl",
                Date = new DateTime(2008, 4, 26),
                Price = 5040,
            });
        }
        public ObservableCollection<Book> BookList { get; set; }
    }
}
```

```MainWindow.xaml
<Window x:Class="_170605_t1450_collectionViewSource.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:_170605_t1450_collectionViewSource"
        xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="720">
    <Window.Resources>
        <local:BooksData x:Key="books"/>
        <CollectionViewSource x:Key="myView" Source="{Binding Source={StaticResource books}, Path=BookList}">
            <CollectionViewSource.SortDescriptions>
                <scm:SortDescription PropertyName="Date"/>
                <scm:SortDescription PropertyName="Price"/>
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>
    </Window.Resources>
    <Grid>
        <ListView Name="listView1" Margin="12"
                  ItemsSource="{Binding Source={StaticResource myView}}"
                  GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler"
                  >
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Title}" Header="書籍名"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Author}" Header="著者"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Date, StringFormat=yyyy年MM月}" Header="出版月"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Price,StringFormat='#,###円'}" Header="価格"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>
```

### 気になった部分

上記のコードで気になったのは以下。

```
private void GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e)
{
    GridViewColumnHeader clickedHeader = e.OriginalSource as GridViewColumnHeader;
```

senderでなくe.OriginalSource を使うのはなぜか。

http://www.wisdomsoft.jp/447.html
> ルーティング・イベント上の本質的なイベント発生源を取得するには、第１パラメータではなく RoutedEventArgs オブジェクトが提供する OriginalSource プロパティを使います。


```
        <ListView Name="listView1" Margin="12"
                  ItemsSource="{Binding Source={StaticResource myView}}"
                  GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler"
                  >
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Title}" Header="書籍名"/>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=Author}" Header="著者"/>
```

以下のように理解した。

ListView内のGridViewColumnHeaderをクリックした場合、senderにはListView が入ってしまう。本質的なイベント発生源(GridViewColumnHeader)を得るためには`e.OriginalSource`を使う。


その他の関連リンク: http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=47348&forum=7