bucket-sort logo bucket-sort

プログラミングとインフラエンジニアリングの覚え書き

  • Posts
  • About
  • Contact
  1. Home
  2. All Posts
  3. [WPF] Window クラスを支える基底クラス

[WPF] Window クラスを支える基底クラス

Aug 22, 2026 C# , .NET bucket-sort

前回は、Window クラスの役割と、ContentControl、Control、FrameworkElement から継承する機能を見ました。

今回は、さらに基底側にあるクラスを見ていきます。

対象は次の 4 つです。

  • System.Windows.UIElement
  • System.Windows.Media.Visual
  • System.Windows.DependencyObject
  • System.Windows.Threading.DispatcherObject

これらは、普段の WPF アプリケーション開発で直接継承する機会は多くありません。しかし、入力イベント、描画、依存関係プロパティ、UI スレッドといった WPF の根本的な仕組みを理解するうえで重要です。

Window の継承階層

Window の代表的な継承階層は次の通りです。

DispatcherObject
  └─ DependencyObject
      └─ Visual
          └─ UIElement
              └─ FrameworkElement
                  └─ Control
                      └─ ContentControl
                          └─ Window

前回扱った FrameworkElement、Control、ContentControl は、アプリケーション開発者が普段よく意識する機能を提供していました。

一方、今回扱うクラスは、WPF の内部構造に近い土台です。

クラス 主な役割
UIElement 入力、フォーカス、イベント、レイアウト参加、表示状態を扱う
Visual 描画、座標変換、ビジュアルツリーの基礎を提供する
DependencyObject 依存関係プロパティシステムを提供する
DispatcherObject オブジェクトを UI スレッドの Dispatcher に関連付ける

System.Windows.UIElement

UIElement は、WPF の UI 要素として振る舞うための基本機能を提供するクラスです。

ここでいう UI 要素とは、画面上に表示され、入力を受け取り、レイアウトに参加し、イベントを発生させる要素のことです。

UIElement の主要メンバーには、次のようなものがあります。

メンバー 役割
IsEnabled 要素が操作可能かどうか
IsVisible 表示されているかどうか
Visibility Visible、Hidden、Collapsed の表示状態
Focusable フォーカスを受け取れるかどうか
IsKeyboardFocused キーボードフォーカスを持っているか
Focus() 要素にフォーカスを移す
InvalidateVisual() 再描画を要求する
Measure() / Arrange() レイアウト計算に関わるメソッド
MouseDown / MouseUp マウス入力イベント
KeyDown / KeyUp キーボード入力イベント

たとえば、Window でキー入力を受け取りたい場合、KeyDown イベントを使えます。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        KeyDown += (s, e) =>
        {
            if (e.Key == Key.Escape)
            {
                Close();
            }
        };
    }
}

このような入力イベントの基礎は、UIElement から提供されています。

Visibility

UIElement の中でもよく使うのが Visibility です。

<TextBlock Text="読み込み中..."
           Visibility="Collapsed" />

Visibility には次の 3 つの値があります。

値 意味
Visible 表示する
Hidden 表示しないが、レイアウト上の領域は残す
Collapsed 表示せず、レイアウト上の領域も取らない

Hidden と Collapsed の違いは重要です。

Hidden は見えないだけで場所は確保されます。Collapsed は存在しないように扱われ、周囲の要素が詰めて配置されます。

ルーティングイベント

UIElement は、WPF のイベントシステムとも深く関係します。

WPF には ルーティングイベント という仕組みがあります。通常の .NET イベントと異なり、イベントが要素ツリーを通って親子方向に伝わります。

代表的なルーティングイベントには、次のようなものがあります。

  • MouseDown
  • PreviewMouseDown
  • KeyDown
  • PreviewKeyDown
  • GotFocus
  • LostFocus

たとえば、Button の中に TextBlock がある場合でも、親要素側でマウスイベントを受け取れます。

<Grid MouseDown="Grid_MouseDown">
    <Button Content="OK" />
</Grid>

このようなイベント伝播の仕組みは、WPF の複雑な UI を扱ううえで重要です。

System.Windows.Media.Visual

Visual は、WPF の描画システムの基礎となるクラスです。

Visual は、画面に表示されるオブジェクトとして、描画、座標変換、クリッピング、ヒットテスト、ビジュアルツリーなどに関わります。

主要な役割は次の通りです。

役割 説明
描画 画面に表示される内容の基礎になる
ビジュアルツリー 表示要素の親子関係を構成する
座標変換 親要素、子要素、画面座標間の変換を行う
ヒットテスト 指定した位置にある表示要素を調べる
クリッピング 表示範囲を制限する

WPF には、論理ツリーとビジュアルツリーという 2 種類のツリーがあります。

論理ツリー は、XAML で定義した要素の意味的な親子関係です。

<Window>
    <Grid>
        <Button Content="OK" />
    </Grid>
</Window>

この場合、論理的には Window の中に Grid があり、その中に Button があります。

一方、ビジュアルツリー は、実際の描画に使われるより細かい親子関係です。Button の中には、テンプレートによって生成された境界線やテキスト表示要素などが含まれます。

Visual は、このビジュアルツリーの基盤になるクラスです。

System.Windows.DependencyObject

DependencyObject は、WPF の依存関係プロパティシステムを利用できるようにする基底クラスです。

WPF では、通常の C# プロパティだけでなく、依存関係プロパティ という特別なプロパティシステムが使われます。

依存関係プロパティは、次のような機能を支えています。

  • データバインディング
  • スタイル
  • アニメーション
  • プロパティ値の継承
  • 既定値
  • 変更通知
  • リソース参照

たとえば、Button.Background や Window.Title、FrameworkElement.Width など、多くの WPF プロパティは依存関係プロパティとして実装されています。

依存関係プロパティは、次のように静的フィールドとして登録されます。

public static readonly DependencyProperty MessageProperty =
    DependencyProperty.Register(
        nameof(Message),
        typeof(string),
        typeof(MyControl),
        new PropertyMetadata("Hello"));

public string Message
{
    get => (string)GetValue(MessageProperty);
    set => SetValue(MessageProperty, value);
}

GetValue や SetValue は DependencyObject が提供するメソッドです。

object value = GetValue(MessageProperty);
SetValue(MessageProperty, "New Message");

つまり、Window が Title、Width、DataContext、Visibility などを WPF らしく扱えるのは、継承階層の中に DependencyObject があるためです。

System.Windows.Threading.DispatcherObject

DispatcherObject は、WPF オブジェクトを Dispatcher に関連付ける基底クラスです。

WPF の UI は、基本的に UI スレッドで操作する必要があります。別スレッドから直接 UI 要素を操作すると例外が発生します。

// バックグラウンドスレッドから直接 UI を操作すると問題になる
Title = "更新しました";

この制約を支えているのが DispatcherObject と Dispatcher です。

DispatcherObject の主要メンバーは次の通りです。

メンバー 役割
Dispatcher 関連付けられた Dispatcher を取得する
CheckAccess() 現在のスレッドからアクセス可能か確認する
VerifyAccess() 現在のスレッドからアクセスできない場合に例外を投げる

バックグラウンド処理から UI を更新したい場合は、Dispatcher.Invoke や Dispatcher.BeginInvoke を使って UI スレッドに処理を戻します。

Dispatcher.Invoke(() =>
{
    Title = "更新しました";
});

CheckAccess() を使うと、現在のスレッドが UI スレッドかどうかを確認できます。

if (CheckAccess())
{
    Title = "更新しました";
}
else
{
    Dispatcher.Invoke(() =>
    {
        Title = "更新しました";
    });
}

Window、Button、TextBox などの WPF UI 要素は、この DispatcherObject の性質を持っています。そのため、UI 要素は作成されたスレッドに属し、別スレッドから自由に操作できないようになっています。

なぜこの階層が重要なのか

Window を使うだけなら、継承階層をすべて暗記する必要はありません。

しかし、WPF で起こる多くの疑問は、この階層を見ると理解しやすくなります。

たとえば、次のような疑問です。

  • なぜ Window に DataContext を設定できるのか
  • なぜ Button に Content として任意の UI 要素を入れられるのか
  • なぜ Visibility を Collapsed にするとレイアウトから消えるのか
  • なぜ別スレッドから UI を更新できないのか
  • なぜ XAML のプロパティがバインディングやアニメーションに対応できるのか

これらは、すべて Window 自身だけでなく、基底クラスから受け継いだ仕組みによって実現されています。

まとめ

Window は、WPF アプリケーションのトップレベルウィンドウを表すクラスです。

その下には、WPF の基盤となる重要なクラスが積み重なっています。

UIElement は入力、フォーカス、表示状態、イベントを提供します。Visual は描画とビジュアルツリーの基盤です。DependencyObject は依存関係プロパティを提供し、バインディング、スタイル、アニメーションを支えます。DispatcherObject は、WPF の UI オブジェクトを UI スレッドに関連付けます。

WPF のクラス階層は一見複雑ですが、それぞれの階層は明確な役割を持っています。

Window を理解するときは、単に「画面を表すクラス」と見るだけでなく、「WPF の入力、描画、プロパティ、スレッド管理の仕組みをすべて受け継いだトップレベル要素」と捉えると、全体像がつかみやすくなります。

C# .NET WPF Window UIElement Visual DependencyObject DispatcherObject
← [WPF] Window クラスの役割と上位クラス [WPF] XAML の構文を理解する: 名前空間とキーワード →

Related Posts

  • [WPF] Window クラスの役割と上位クラス Aug 21, 2026
  • [WPF] XAML の構文を理解する: 名前空間とキーワード Aug 23, 2026
  • [WPF] Application クラスの役割 Aug 20, 2026
  • [WPF] WPF の主要アセンブリと名前空間 Aug 19, 2026

Table of Contents

  • Window の継承階層
  • System.Windows.UIElement
  • Visibility
  • ルーティングイベント
  • System.Windows.Media.Visual
  • System.Windows.DependencyObject
  • System.Windows.Threading.DispatcherObject
  • なぜこの階層が重要なのか
  • まとめ

Recent Posts

  • [WPF] XAML の構文を理解する: 名前空間とキーワード Aug 23, 2026
  • [WPF] Window クラスを支える基底クラス Aug 22, 2026
  • [WPF] Window クラスの役割と上位クラス Aug 21, 2026
  • [WPF] Application クラスの役割 Aug 20, 2026
  • [WPF] WPF の主要アセンブリと名前空間 Aug 19, 2026

Categories

  • C#165
  • .NET164
  • AWS27
  • Entity Framework Core24
  • Laravel16
  • Linux15
  • MySQL9
  • Apache8
  • PHP8
  • Data Access6
  • DynamoDB6
  • セキュリティ6
  • Nginx5
  • WordPress4
  • インフラ4
  • テスト4
  • Hugo3
  • .NET Framework1
  • Aurora1
  • Diagnostics1

Tags

  • C#
  • .NET
  • Entity Framework Core
  • AWS
  • Laravel
  • コレクション
  • PHP
  • セキュリティ
  • MySQL
  • Linux
  • パフォーマンス
  • LINQ
  • WPF
  • Apache
  • SQL Server
  • System.Collections.Generic
  • デリゲート
  • リフレクション
  • ADO.NET
  • Code Snippet
  • DbContext
  • DynamoDB
  • NoSQL
  • PHP-FPM
  • RDS
  • System.Collections
  • Windows
  • メタデータ
  • メモリ管理
  • CIL
  • DoS
  • Nginx
  • WordPress
  • アセンブリ
  • ラムダ式
  • 監視
  • 設計
  • Amazon Linux 2023
  • Delegate
  • Docker
  • IDisposable
  • Ipset
  • Iptables
  • LINQ to Objects
  • Migration
  • OPCache
  • Pointer
  • Reflection
  • System.Collections.Specialized
  • Unsafe
Powered by Hugo & Explore Theme.