none
DataGridHeaderBorderについて RRS feed

  • 質問

  • DataGridの行ヘッダーをダブルクリックしたらある操作を行うプログラムを作っています。

    if (e.OriginalSource.GetType() != typeof(Microsoft.Windows.Themes.DataGridHeaderBorder))

    として、判定しているのですが、行ヘッダーをダブルクリックしてもfalseとなります。

    もちろんe.OriginalSourceはMicrosoft.Windows.Themes.DataGridHeaderBorderとなってるのですがなぜでしょうか?

     

    e.OriginalSource.GetType() != typeof(Microsoft.Windows.Themes.DataGridHeaderBorder)をイミディエイトウィンドウでみると

    型 'Microsoft.Windows.Themes.DataGridHeaderBorder' は 'PresentationFramework.Classic.dll' および 'PresentationFramework.Luna.dll の両方に存在します。

    と表示されるのが原因と思われるのですが、どうやって解決すればよいでしょうか?

     

    参照設定にはPresentationFramework.Classic.dllのみ追加していてPresentationFramework.Luna.dllは追加していません。

    環境はVisual Studio 2010です。

    よろしくお願いします。

     

    2010年5月18日 5:36

回答

  • if (e.OriginalSource.GetType() != typeof(Microsoft.Windows.Themes.DataGridHeaderBorder))

    として、判定しているのですが、行ヘッダーをダブルクリックしてもfalseとなります。

    まず、オブジェクトがある型であるかどうかは、GetType() と typeof() を比較するのではなく、is 演算子を使って obj is T という形で判定しましょう。GetType() とかが必要なのは派生クラスを除かなければならないときとかぐらいで、ほとんどの場合はその必要はありません。

    e.OriginalSource.GetType() != typeof(Microsoft.Windows.Themes.DataGridHeaderBorder)をイミディエイトウィンドウでみると

    型 'Microsoft.Windows.Themes.DataGridHeaderBorder' は 'PresentationFramework.Classic.dll' および 'PresentationFramework.Luna.dll の両方に存在します。

    と表示されるのが原因と思われるのですが、どうやって解決すればよいでしょうか?

     

    参照設定にはPresentationFramework.Classic.dllのみ追加していてPresentationFramework.Luna.dllは追加していません。

    DataGridHeaderBorder がいずれの(あるいは第三の――例えば PresentationFramework.Aero.dll とか――)dll(アセンブリ)に含まれるインスタンスなのかは、システムに適用されているテーマによって実行時に決定されます。そして名前空間を含めたクラス名が同じであっても、アセンブリが異なれば別の型であり、== とかは false を返します。

    具体的にそのインスタンスがどのアセンブリに属しているかは、イミディエイトウィンドウで e.OriginalSource.GetType().AssemblyQualifiedName などと評価してみれば確認できます。

     

    さて本題ですが、そもそもわざわざ OriginalSource を見なくても、Source が DataGridRow かどうかを見るだけで十分ではないでしょうか? そうでないと、例えば DataGrid.RowHeaderTemplate で行ヘッダに TextBlock を表示したとき、OriginalSource はクリックする場所によって TextBlock になったり DataGridHeaderBorder になったりと判断が面倒なことになります。

    • 回答としてマーク yty0918 2010年5月24日 8:14
    2010年5月18日 6:46

すべての返信

  • if (e.OriginalSource.GetType() != typeof(Microsoft.Windows.Themes.DataGridHeaderBorder))

    として、判定しているのですが、行ヘッダーをダブルクリックしてもfalseとなります。

    まず、オブジェクトがある型であるかどうかは、GetType() と typeof() を比較するのではなく、is 演算子を使って obj is T という形で判定しましょう。GetType() とかが必要なのは派生クラスを除かなければならないときとかぐらいで、ほとんどの場合はその必要はありません。

    e.OriginalSource.GetType() != typeof(Microsoft.Windows.Themes.DataGridHeaderBorder)をイミディエイトウィンドウでみると

    型 'Microsoft.Windows.Themes.DataGridHeaderBorder' は 'PresentationFramework.Classic.dll' および 'PresentationFramework.Luna.dll の両方に存在します。

    と表示されるのが原因と思われるのですが、どうやって解決すればよいでしょうか?

     

    参照設定にはPresentationFramework.Classic.dllのみ追加していてPresentationFramework.Luna.dllは追加していません。

    DataGridHeaderBorder がいずれの(あるいは第三の――例えば PresentationFramework.Aero.dll とか――)dll(アセンブリ)に含まれるインスタンスなのかは、システムに適用されているテーマによって実行時に決定されます。そして名前空間を含めたクラス名が同じであっても、アセンブリが異なれば別の型であり、== とかは false を返します。

    具体的にそのインスタンスがどのアセンブリに属しているかは、イミディエイトウィンドウで e.OriginalSource.GetType().AssemblyQualifiedName などと評価してみれば確認できます。

     

    さて本題ですが、そもそもわざわざ OriginalSource を見なくても、Source が DataGridRow かどうかを見るだけで十分ではないでしょうか? そうでないと、例えば DataGrid.RowHeaderTemplate で行ヘッダに TextBlock を表示したとき、OriginalSource はクリックする場所によって TextBlock になったり DataGridHeaderBorder になったりと判断が面倒なことになります。

    • 回答としてマーク yty0918 2010年5月24日 8:14
    2010年5月18日 6:46
  • 回答ありがとうございます。

    比較はis演算子を使うことにしました。

    e.OriginalSource.GetType().AssemblyQualifiedNameで評価してみると、PresentationFramework.Aeroになっていましたので、

    参照の設定でPresentationFramework.Classic.dllを削除して、PresentationFramework.Aero.dllを追加すると

    if (!(e.OriginalSource is DataGridHeaderBorder))の結果がfalseとなり期待通りの結果となりました。

    (質問時にfalseが正しくないと書いてましたが、falseで正しい動作でした。) 

     

    しかし、OSがWindows7のときはこれでよかったのですが、WindowsXpになるとうまくいきませんでした。

    e.OriginalSource.GetType().AssemblyQualifiedNameを評価するとPresentationFramework.Classicとなっていましたので、

    参照の設定でPresentationFramework.Classic.dllを追加したのですが、コンパイルエラーになります。

    どうたいしょすればよいでしょうか?

    2010年5月19日 4:16
  • OriginalSourceとかではなく、マウスの位置で判断するというのはどうでしょう?

    private void DataGrid_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
      var dg = e.Source as DataGrid;
      var pos = e.GetPosition(dg);
      if (dg.RowHeaderActualWidth > pos.X)
      {
        // 行ヘッダーでダブルクリックされた
      }
    }
    
    上のような感じでいけるかな。


    かずき Blog:http://blogs.wankuma.com/kazuki/
    2010年5月19日 14:30