Skip to content

MS_WPFControls

nishi_74322014 edited this page Aug 21, 2026 · 1 revision

WPFのコントロール

  • 戻る(WPF

概要

標準コントロール

WPF は、次のような標準コントロールを備えている。

コントロール(Control)

ボタンやリストボックスなどのコントロール類

一例

  • Label
  • TextBox
  • Button
  • ComboBox
  • ListBox
  • DataGrid

パネル(Panel)

子要素の配置を決める。

一例

  • Canvas
  • DockPanel
  • StackPanel
  • WrapPanel
  • UniformGrid
  • Grid

シェイプ(Shape)

ベクタグラフィックスを描画

一例

  • Rectangle
  • Ellipse
  • Path

メディア(FrameworkElement)

静止画や動画などの表示

一例

  • Image
  • MediaElement

ドキュメント(TextBoxBase)

文書整形

一例

  • RichTextBox

補足(この分類の背景にある WPF のクラス階層): 5 つの分類は
WPF のクラス階層に対応しているため、
階層を示すと理解しやすい。

DispatcherObject          … UI スレッド親和性([ウィンドウ・システム](MS_WindowSystem))
 └ DependencyObject        … 【依存関係プロパティ】を持てる ★
     └ Visual              … 描画
         └ UIElement       … 入力・イベント・レイアウト
             └ FrameworkElement  … スタイル、データ バインディング、ツリー
                 ├ Panel             … 【子要素を配置する】
                 ├ Shape             … ベクタ描画
                 ├ Image / MediaElement
                 └ Control           … 【テンプレートを持つ】★
                     ├ ContentControl    … 子が【1 つ】(Button、Label)
                     ├ ItemsControl      … 子が【複数】(ListBox、DataGrid)
                     └ TextBoxBase       … 文書編集

Control かどうかが決定的な違いである。

【Control を継承する】
   ・ControlTemplate を持つ=【見た目を丸ごと差し替えられる】★
   ・Background / Foreground / FontSize 等の共通プロパティを持つ

【Control を継承しない】(Panel、Shape、Image)
   ・テンプレートがない= 見た目は自前の描画ロジックで決まる
   ・Style は当たるが、ControlTemplate は当たらない

ContentControlItemsControl の対比が、
XAMLの書き方(1) の主題の 1 つでもある。

ContentControl … Content プロパティ(object 1 つ)
                  → DataTemplate で「1 件をどう描くか」を決める
ItemsControl   … ItemsSource(コレクション)
                  → ItemTemplate で「1 件をどう描くか」
                  → ItemsPanelTemplate で「並べ方」
                  → ControlTemplate で「全体の枠」

ユーザ コントロール

ユーザ コントロールは、UI 要素の部品化を目的としたもので、
Windows フォーム、ASP.NET アプリケーション(Web フォーム)などと同様に、
ユーザ コントロールの開発・使用が可能である。

WPF では、

  • ユーザ コントロールの CLR プロパティを初期化する場合、XAML 要素から指定可能であったり、
  • ユーザ コントロール内の各コントロールに「データ バインディング」する場合は、
    • ユーザ コントロールの DataContext プロパティに「バインディング ソース」を
      指定可能であったり、
    • また、「ツールチップ」の表示にユーザ コントロールを設定したりするなど、

ユーザ コントロールをより柔軟に利用できる。

補足(UserControlCustomControl の使い分け): 本節が扱うのは
UserControl だが、WPF にはもう 1 つの部品化の方式があるので
対比しておく(参考リンクの「コントロールの作成の概要」の主題でもある)。

UserControl CustomControl(Control 派生)
作り方 XAML で組み立てる コードで作り、テンプレートを別に持つ
見た目の差し替え できない(固定) ControlTemplate で丸ごと変えられる
作成の手間 少ない 多い
テーマ対応 しにくい Themes/Generic.xaml で対応
再利用の範囲 アプリ内 ライブラリとして配布できる
【判断の目安】
   ・そのアプリ専用の画面部品        → 【UserControl】★
   ・見た目を変えて使い回す部品       → CustomControl
   ・社内共通のコントロール ライブラリ → CustomControl

 → 迷ったら UserControl から始めてよい
   (必要になってから CustomControl へ作り直す)

画面遷移での利用

  • ユーザ コントロールをプログラムからインスタンス化して、
    (ナビゲーション フレームワークの仕様に依らず)
    画面遷移やダイアログの代替を実現したりできる。
  • ダイアログがサポートされていない「XBAP」で、z-index を適切に設定するか、
    最後の要素としてルートのパネル要素に追加することで、
    ダイアログ表示の代替が可能
    (Silverlight ver3 から、ChildWindow コントロールが利用できる)。
  • ユーザ コントロールにアニメーションを適用することで、
    アニメーション効果付の画面遷移を実装することができる。

補足(この手法は現在の主流である): 「ユーザ コントロールを
差し替えて画面遷移を実現する」という手法は、
現在の MVVM では標準的な作法になっている。

【ナビゲーション フレームワーク(NavigationWindow / Frame)】
   ・ブラウザ的な戻る/進むを持つ
   ・[XAMLの書き方(2)](MS_XAMLWriting2) の NavigationService
   ・業務アプリでは【かえって扱いにくい】ことが多い
      → 画面の状態管理が独自
      → MVVM と噛み合わせにくい

【ContentControl + DataTemplate 方式】★ 現在の定石
   <ContentControl Content="{Binding CurrentViewModel}" />

   <DataTemplate DataType="{x:Type vm:LoginViewModel}">
       <v:LoginView />
   </DataTemplate>
   <DataTemplate DataType="{x:Type vm:MainViewModel}">
       <v:MainView />
   </DataTemplate>

   → 【ViewModel を差し替えるだけで View が切り替わる】★
   → View(UserControl)と ViewModel の対応が宣言的に書ける
   → 遷移ロジックが ViewModel 側に閉じる(テストできる)

移行メモ(XBAP は廃止済み): 本節が言及する
XBAP(XAML Browser Application)は、
ブラウザのプラグイン廃止に伴い使えなくなった

・IE の終了(2022)
・.NET Framework 4.8 では動作するが、対応ブラウザがない
・【.NET(Core 系)には移植されていない】

【現在、Web で XAML 的な UI を動かすなら】
   ・[Blazor](MS_Blazor)(HTML ベースだが、コンポーネント指向)
   ・[Uno Platform](MS_UnoPlatform)(XAML を WebAssembly で)
      → [WebAssembly](MS_WebAssembly) 参照

Silverlight も同様にサポートが終了している
Silverlight)。

部品の汎用化

ユーザ コントロールのプロパティを以下の用途で使用する場合、
それぞれ追加の実装が必要になるので注意する。

バインディング ソース

変更通知を実装した「バインディング ソース」として使用する場合、
INotifyPropertyChanged インターフェイス、変更通知処理を実装する必要がある。

バインディング ターゲット

変更監視・有効値検証を実装した「バインディング ターゲット」として使用する場合、
DependencyObject クラスを継承し、「依存関係プロパティ」として実装する必要がある。

補足(この 2 つの区別が WPF で最も重要): 原文の指摘は
WPF の設計の核心を突いているので、具体化しておく。

【バインディングの向き】

   バインディング ソース  ──────▶  バインディング ターゲット
   (通常は ViewModel)              (通常は UI 要素)

   ソース側に必要   … INotifyPropertyChanged(変更を通知する)
   ターゲット側に必要 … 依存関係プロパティ(変更を受け取る)★

① ソース側(INotifyPropertyChanged

public class MyViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    private string _name = "";
    public string Name
    {
        get => _name;
        set { _name = value; OnPropertyChanged(); }
    }
    void OnPropertyChanged([CallerMemberName] string? p = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
}
【実装しないとどうなるか】★
   ・初回の表示はされる
   ・【値を変えても画面が更新されない】
   → 「バインディングが効かない」の最頻出の原因
   → エラーも例外も出ないので気付きにくい

② ターゲット側(依存関係プロパティ)

public partial class MyUserControl : UserControl
{
    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.Register(
            nameof(Title), typeof(string), typeof(MyUserControl),
            new FrameworkPropertyMetadata("", OnTitleChanged));

    public string Title
    {
        get => (string)GetValue(TitleProperty);
        set => SetValue(TitleProperty, value);
    }
    static void OnTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { }
}
【CLR プロパティのままだとどうなるか】★
   <local:MyUserControl Title="{Binding SomeValue}" />
     → 【実行時に例外】
       「'Title' プロパティに 'Binding' を設定できません。
         DependencyObject の DependencyProperty にのみ設定できます」

 → 原文の「依存関係プロパティとして実装する必要がある」は
   この制約を指している

依存関係プロパティが提供するもの(なぜ必要か):

・【バインディングのターゲットになれる】★
・スタイル / テンプレート / トリガーから設定できる
   → [XAMLの書き方(1)](MS_XAMLWriting1) の Style / Trigger
・アニメーションの対象になれる
・【値の優先順位】(既定値 < スタイル < ローカル値 < アニメーション)
・【値の継承】(FontSize 等が子要素に伝わる)
・値の検証・強制(ValidateValueCallback / CoerceValueCallback)
・メモリ効率(既定値のままなら記憶領域を消費しない)

現在の簡略化:

// .NET Community Toolkit(MVVM Toolkit)
[ObservableObject]
public partial class MyViewModel
{
    [ObservableProperty] private string _name = "";   // ← 自動生成される ★
}
【Source Generator による生成】
   ・INotifyPropertyChanged の定型コードが不要になる
   ・[RelayCommand] でコマンドも生成できる
   → [XAMLの書き方(2)](MS_XAMLWriting2) の MVVM の節も参照

参考

Microsoft Learn


Tags: 移行, .NET開発, UIサブシステム, WPF/Silverlight, XAML

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally