Wpf-quick-guide

提供:Dev Guides
移動先:案内検索

WPF-概要

WPFはWindows Presentation Foundationの略です。 Windowsアプリケーションを構築するための強力なフレームワークです。 このチュートリアルでは、WPFアプリケーションを構築するために理解する必要がある機能と、それがWindowsアプリケーションに根本的な変化をもたらす方法について説明します。

WPFは最初に.NET Framework 3.0バージョンで導入され、その後、他の多くの機能が後続の.NET Frameworkバージョンで追加されました。

WPFアーキテクチャ

WPF以前は、MFCやWindowsフォームなど、Microsoftが提供する他のユーザーインターフェイスフレームワークは、User32およびGDI32 DLLの単なるラッパーでしたが、WPFはUser32を最小限しか使用しません。 So,

  • WPFは単なるラッパーではありません。
  • これは、.NETフレームワークの一部です。
  • マネージコードとアンマネージコードが混在しています。

WPFアーキテクチャの主要なコンポーネントは、次の図に示すとおりです。 WPFの最も重要なコード部分は-

  • プレゼンテーションフレームワーク
  • プレゼンテーションコア
  • ミルコア

WPFアーキテクチャ

プレゼンテーションフレームワーク*および*プレゼンテーションコア*はマネージコードで記述されています。 *Milcore はアンマネージコードの一部であり、DirectXとの緊密な統合を可能にします(表示とレンダリングを担当)。 CLR は、メモリ管理、エラー処理などの多くの機能を提供することにより、開発プロセスの生産性を向上させます。

WPF –利点

以前のGUIフレームワークでは、アプリケーションの外観と動作の間に実質的な分離はありませんでした。 GUIと動作の両方が同じ言語で作成されました。 C#またはVB.Net。UIとそれに関連する動作の両方を実装するには、開発者のさらなる努力が必要です。

WPFでは、UI要素はXAMLで設計され、動作はC#やVB.Netなどの手続き型言語で実装できます。 そのため、動作をデザイナーコードから分離するのは非常に簡単です。

XAMLを使用すると、プログラマーはデザイナーと並行して作業できます。 GUIとその動作を分離することで、スタイルとテンプレートを使用してコントロールの外観を簡単に変更できます。

WPF –機能

WPFは、Windowsアプリケーションを作成するための強力なフレームワークです。 それは多くの素晴らしい機能をサポートしており、そのうちのいくつかは以下にリストされています-

Feature Description
Control inside a Control Allows to define a control inside another control as a content.
Data binding Mechanism to display and interact with data between UI elements and data object on user interface.
Media services Provides an integrated system for building user interfaces with common media elements like images, audio, and video.
Templates In WPF you can define the look of an element directly with a Template
Animations Building interactivity and movement on user Interface
Alternative input Supports multi-touch input on Windows 7 and above.
Direct3D Allows to display more complex graphics and custom themes

WPF-環境設定

Microsoftは、WPFアプリケーション開発用に2つの重要なツールを提供しています。

  • ビジュアルスタジオ
  • 発現ブレンド

どちらのツールでもWPFプロジェクトを作成できますが、事実、開発者はVisual Studioをより多く使用し、デザイナーはBlendをより頻繁に使用します。 このチュートリアルでは、主にVisual Studioを使用します。

インストール

Microsoftは、https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx [VisualStudio]からダウンロードできるVisual Studioの無料バージョンを提供しています。

ファイルをダウンロードし、以下の手順に従って、システムにWPFアプリケーション開発環境をセットアップします。

  • ダウンロードが完了したら、*インストーラー*を実行します。 次のダイアログが表示されます。

インストーラー

  • [インストール]ボタンをクリックすると、インストールプロセスが開始されます。

インストールプロセス

  • インストールプロセスが正常に完了すると、次のダイアログボックスが表示されます。

ダイアログボックス

  • このダイアログボックスを閉じて、必要に応じてコンピューターを再起動します。
  • 次のダイアログボックスを開く[スタート]メニューからVisual Studioを開きます。

Visual Studio

  • すべてが完了すると、Visual Studioのメインウィンドウが表示されます。

Visual Studioのウィンドウ

これで、最初のWPFアプリケーションを構築する準備ができました。

WPF-Hello World

この章では、単純なHello World WPFアプリケーションを開発します。 以下の手順に従って、簡単な実装を始めましょう。

  • [ファイル]> [新規]> [プロジェクト]メニューオプションをクリックします。

プロジェクトメニューオプション

  • 次のダイアログボックスが表示されます。

新規プロジェクトダイアログボックス

  • [テンプレート]で[Visual C#]を選択し、中央のパネルで[WPFアプリケーション]を選択します。
  • プロジェクトに名前を付けます。 名前フィールドに HelloWorld と入力し、[OK]ボタンをクリックします。
  • デフォルトでは、2つのファイルが作成されます。1つは XAML ファイル(mainwindow.xaml)、もう1つは CS ファイル(mainwindow.cs)です。
  • mainwindow.xamlには、2つのサブウィンドウが表示されます。1つは design window で、もう1つは source (XAML) window です。
  • WPFアプリケーションでは、アプリケーションのUIを設計する2つの方法があります。 1つは、UI要素をツールボックスからデザインウィンドウにドラッグアンドドロップすることです。 2番目の方法は、UI要素のXAMLタグを記述してUIを設計することです。 Visual Studioは、UI設計にドラッグアンドドロップ機能を使用するときにXAMLタグを処理します。
  • mainwindow.xamlファイルでは、デフォルトで次のXAMLタグが書き込まれます。
<Window x:Class = "HelloWorld.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
   </Grid>

</Window>
  • デフォルトでは、グリッドはページの後の最初の要素として設定されます。
  • ツールボックスに移動して、TextBlockをデザインウィンドウにドラッグします。

ツールボックス

  • デザインウィンドウにTextBlockが表示されます。

TextBlock

  • ソースウィンドウを見ると、Visual StudioがTextBlockのXAMLコードを生成していることがわかります。
  • XAMLコードのTextBlockのTextプロパティをTextBlockからHello Worldに変更しましょう。
<Window x:Class = "HelloWorld.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <TextBlock x:Name = "textBlock" HorizontalAlignment = "Left"
         Margin = "235,143,0,0" TextWrapping = "Wrap" Text = "Hello World!"
         VerticalAlignment = "Top" Height = "44" Width = "102"/>
   </Grid>

</Window>
  • これで、デザインウィンドウにも変更が表示されます。

デザインウィンドウ

上記のコードをコンパイルして実行すると、次のウィンドウが表示されます。

最初のWPFアプリケーション

おめでとうございます。 最初のWPFアプリケーションを設計および作成しました。

WPF-XAMLの概要

WPFでの作業中に最初に遭遇することの1つは、XAMLです。 XAMLはExtensible Application Markup Languageの略です。 XMLに基づいたシンプルで宣言型の言語です。

  • XAMLでは、階層関係を持つオブジェクトのプロパティの作成、初期化、および設定が非常に簡単です。
  • 主にGUIの設計に使用されますが、Workflow Foundationでワークフローを宣言するなど、他の目的にも使用できます。

基本的な構文

新しいWPFプロジェクトを作成すると、以下に示すように、MainWindow.xamlでデフォルトでXAMLコードの一部に遭遇します。

<Window x:Class = "Resources.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "525">

   <Grid>

   </Grid>

</Window>

上記のXAMLファイルには、さまざまな種類の情報が含まれています。 次の表は、各情報の役割を簡単に説明しています。

Information Description
<Window It is the opening object element or container of the root.
x:Class = "Resources.MainWindow" It is a partial class declaration which connects the markup to the partial class code defined behind.
xmlns = "http://schemas.microsoft.com/win fx/2006/xaml/presentation" Maps the default XAML namespace for WPF client/framework
xmlns:x = "http://schemas.microsoft.com/w infx/2006/xaml" XAML namespace for XAML language which maps it to x: prefix
> End of object element of the root

<Grid>

</Grid>

It is starting and closing tags of an empty grid object.
</Window> Closing the object element

XAMLの構文規則は、XMLにほぼ似ています。 XAMLドキュメントを見ると、それが実際に有効なXMLファイルであることに気付くでしょうが、XMLファイルは必ずしもXAMLファイルではありません。 これは、XMLでは属性の値が文字列である必要がある一方、XAMLでは、プロパティ要素構文として知られる別のオブジェクトになることができるためです。

  • Object要素の構文は、左山括弧(<)で始まり、その後にオブジェクトの名前が続きます。 ボタン。
  • そのオブジェクト要素のいくつかのプロパティと属性を定義します。
  • Object要素は、スラッシュ(/)に続いてすぐに右山括弧(>)が続く必要があります。

子要素のない単純なオブジェクトの例

<Button/>

いくつかの属性を持つオブジェクト要素の例

<Button Content = "Click Me" Height = "30" Width = "60"/>

プロパティを定義する代替構文の例(プロパティ要素の構文)

<Button>
   <Button.Content>Click Me</Button.Content>
   <Button.Height>30</Button.Height>
   <Button.Width>60</Button.Width>
</Button>

子要素を持つオブジェクトの例:StackPanelには子要素としてTextblockが含まれます

<StackPanel Orientation = "Horizontal">
   <TextBlock Text = "Hello"/>
</StackPanel>

WPFでXAMLを使用する理由

XAMLはWPFの最も広く知られている機能であるだけでなく、最も誤解されている機能の1つでもあります。 WPFを使用している場合は、XAMLについて聞いたことがあるはずです。ただし、XAMLに関する次の2つのあまり知られていない事実に注意してください-

  • WPFはXAMLを必要としません
  • XAMLはWPFを必要としません

実際、それらは分離可能なテクノロジーです。 それがどのようになるかを理解するために、XAMLのいくつかのプロパティでボタンが作成される簡単な例を見てみましょう。

<Window x:Class = "WPFXAMLOverview.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604">

   <StackPanel>
      <Button x:Name = "button" Content = "Click Me" HorizontalAlignment = "Left"
         Margin = "150" VerticalAlignment = "Top" Width = "75"/>
   </StackPanel>

</Window>

WPFでXAMLを使用しないことを選択した場合、手続き型言語でも同じGUI結果を達成できます。 同じ例を見てみましょうが、今回はC#でボタンを作成します。

using System.Windows;
using System.Windows.Controls;

namespace WPFXAMLOverview {
  ///<summary>
     ///Interaction logic for MainWindow.xaml
  ///</summary>

   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();

        //Create the StackPanel
         StackPanel stackPanel = new StackPanel();
         this.Content = stackPanel;

        //Create the Button
         Button button = new Button();
         button.Content = "Click Me";
         button.HorizontalAlignment = HorizontalAlignment.Left;
         button.Margin = new Thickness(150);
         button.VerticalAlignment = VerticalAlignment.Top;
         button.Width = 75;
         stackPanel.Children.Add(button);
      }
   }
}

XAMLコードまたはC#コードのいずれかをコンパイルして実行すると、以下に示すものと同じ出力が表示されます。

XAML出力

上記の例から、オブジェクトのプロパティを作成、初期化、および設定するためにXAMLでできること、コードを使用して同じタスクを実行できることは明らかです。

  • XAMLは、UI要素を設計するためのもう1つのシンプルで簡単な方法です。
  • XAMLを使用すると、UI要素を設計するためにできることが唯一の方法であるとは限りません。 XAMLでオブジェクトを宣言するか、コードを使用してオブジェクトを定義できます。
  • XAMLはオプションですが、それにもかかわらず、WPF設計の中心にあります。
  • XAMLの目標は、ビジュアルデザイナーがユーザーインターフェイス要素を直接作成できるようにすることです。
  • WPFは、マークアップからユーザーインターフェイスのすべての視覚的側面を制御できるようにすることを目的としています。

WPF-要素ツリー

プログラマーがオブジェクトを簡単に処理し、アプリケーションの動作を変更できるように、要素とコンポーネントをツリー構造で並べる多くの技術があります。 Windows Presentation Foundation(WPF)には、オブジェクト形式の包括的なツリー構造があります。 WPFでは、完全なオブジェクトツリーが概念化される2つの方法があります-

  • 論理ツリー構造
  • ビジュアルツリー構造

これらのツリー構造を使用すると、UI要素間の関係を簡単に作成および識別できます。 ほとんどの場合、WPFの開発者と設計者は、手続き型言語を使用してアプリケーションを作成するか、オブジェクトツリー構造を念頭に置いてXAMLでアプリケーションのUI部分を設計します。

論理ツリー構造

WPFアプリケーションでは、XAMLのUI要素の構造は論理ツリー構造を表します。 XAMLでは、UIの基本要素は開発者によって宣言されます。 WPFの論理ツリーは次を定義します-

  • 依存関係プロパティ
  • 静的および動的リソース
  • 名前などに要素をバインドする

ボタンとリストボックスが作成される次の例を見てみましょう。

<Window x:Class = "WPFElementsTree.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604">

   <StackPanel>
      <Button x:Name = "button" Height = "30" Width = "70" Content = "OK" Margin = "20"/>

      <ListBox x:Name = "listBox" Height = "100" Width = "100" Margin = "20">
         <ListBoxItem Content = "Item 1"/>
         <ListBoxItem Content = "Item 2"/>
         <ListBoxItem Content = "Item 3"/>
      </ListBox>

   </StackPanel>

</Window>

XAMLコードを見ると、ツリー構造、つまり ルートノードはウィンドウであり、ルートノード内には子が1つだけあります。それはStackPanelです。 ただし、StackPanelには、ボタンとリストボックスという2つの子要素が含まれています。 リストボックスには、さらに3つの子リストボックス項目があります。

ビジュアルツリー構造

WPFでは、ビジュアルツリーの概念は、ビジュアルベースクラスによって表されるビジュアルオブジェクトの構造を記述します。 出力画面にレンダリングされるすべてのUI要素を示します。

プログラマが特定のコントロール用のテンプレートを作成する場合、実際にはそのコントロールのビジュアルツリーをレンダリングしています。 ビジュアルツリーは、パフォーマンスと最適化の理由で低レベルのコントロールを描画する場合にも非常に便利です。

WPFアプリケーションでは、視覚的なツリーが使用されます-

  • ビジュアルオブジェクトのレンダリング。
  • レイアウトのレンダリング。
  • ルーティングされたイベントは、主に論理ツリーではなく視覚ツリーに沿って移動します。

ボタンとリストボックスを含む上記の簡単なアプリケーションのビジュアルツリーを表示するには、XAMLコードをコンパイルして実行します。次のウィンドウが表示されます。

ビジュアルツリー構造

アプリケーションの実行中は、以下に示すように、実行中のアプリケーションのビジュアルツリーがLive Visual Treeウィンドウに表示され、このアプリケーションの完全な階層が表示されます。

logical_tree

通常、ビジュアルツリーは論理ツリーのスーパーセットです。 ここでは、すべての論理要素もビジュアルツリーに存在していることがわかります。 したがって、これら2つのツリーは、UIを構成するオブジェクトの同じセットの2つの異なるビューにすぎません。

  • 論理ツリーには多くの詳細が含まれていないため、ユーザーインターフェースのコア構造に集中し、表示方法の詳細を無視できます。
  • 論理ツリーは、ユーザーインターフェイスの基本構造を作成するために使用するものです。
  • ビジュアルツリーは、プレゼンテーションに焦点を合わせている場合に役立ちます。 たとえば、UI要素の外観をカスタマイズする場合は、ビジュアルツリーを使用する必要があります。

WPF-依存関係プロパティ

WPFアプリケーションでは、依存関係プロパティはCLRプロパティを拡張する特定のタイプのプロパティです。 WPFプロパティシステムで利用可能な特定の機能を利用します。

依存関係プロパティを定義するクラスは、 DependencyObject クラスから継承する必要があります。 XAMLで使用されるUIコントロールクラスの多くは、 DependencyObject クラスから派生しており、依存関係プロパティをサポートしています。 ボタンクラスは、 IsMouseOver 依存プロパティをサポートします。

次のXAMLコードは、いくつかのプロパティを持つボタンを作成します。

<Window x:Class = "WPFDependencyProperty.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local = "clr-namespace:WPFDependencyProperty"
   Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <Button  Height = "40" Width = "175" Margin = "10" Content = "Dependency Property">
         <Button.Style>
            <Style TargetType = "{x:Type Button}">
               <Style.Triggers>

                  <Trigger Property = "IsMouseOver" Value = "True">
                     <Setter Property = "Foreground" Value = "Red"/>
                  </Trigger>

               </Style.Triggers>
            </Style>
         </Button.Style>
      </Button>
   </Grid>

</Window>

XAMLのx:Typeマークアップ拡張機能には、C#のtypeof()などの同様の機能があります。 <Style TargetType = "\ {x:Type Button}">などのオブジェクトのタイプを取る属性が指定されている場合に使用されます

上記のコードをコンパイルして実行すると、次の MainWindow が表示されます。 マウスがボタンの上にあるとき、ボタンの前景色を変更します。 マウスがボタンを離れると、元の色に戻ります。

依存プロパティ

依存関係プロパティが必要な理由

依存関係プロパティを使用すると、アプリケーションであらゆる種類の利点が得られます。 依存関係プロパティは、次のシナリオでCLRプロパティを介して使用できます-

  • スタイルを設定する場合
  • データバインディングが必要な場合
  • リソース(静的または動的リソース)で設定する場合
  • アニメーションをサポートする場合

基本的に、依存関係プロパティは、CLRプロパティを使用しても得られない多くの機能を提供します。

依存関係プロパティ*と他の CLRプロパティ*の主な違いは以下のとおりです-

  • CLRプロパティは、 getter および setter を使用して、クラスのプライベートメンバーから直接読み書きできます。 対照的に、依存関係プロパティはローカルオブジェクトに保存されません。
  • 依存関係プロパティは、DependencyObjectクラスによって提供されるキー/値ペアの辞書に保存されます。 また、変更時にプロパティを保存するため、多くのメモリを節約します。 XAMLでもバインドできます。

カスタム依存関係プロパティ

  • システムコールregisterで* dependencyプロパティ*を宣言して登録します。
  • プロパティの setter および getter を指定します。
  • グローバルに発生する変更を処理する* staticハンドラ*を定義します
  • 特定のインスタンスに発生する変更を処理する*インスタンスハンドラ*を定義します。

次のC#コードは、依存関係プロパティを定義して、ユーザーコントロールの SetText プロパティを設定します。

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;

namespace WpfApplication3 {
  ///<summary>
     ///Interaction logic for UserControl1.xaml
  ///</summary>

   public partial class UserControl1 : UserControl {

      public UserControl1() {
         InitializeComponent();
      }

      public static readonly DependencyProperty SetTextProperty =
         DependencyProperty.Register("SetText", typeof(string), typeof(UserControl1), new
            PropertyMetadata("", new PropertyChangedCallback(OnSetTextChanged)));

      public string SetText {
         get { return (string)GetValue(SetTextProperty); }
         set { SetValue(SetTextProperty, value); }
      }

      private static void OnSetTextChanged(DependencyObject d,
         DependencyPropertyChangedEventArgs e) {
         UserControl1 UserControl1Control = d as UserControl1;
         UserControl1Control.OnSetTextChanged(e);
      }

      private void OnSetTextChanged(DependencyPropertyChangedEventArgs e) {
         tbTest.Text = e.NewValue.ToString();
      }
   }
}

TextBlockがユーザーコントロールとして定義され、SetText依存関係プロパティによってTextプロパティが割り当てられるXAMLファイルを次に示します。

次のXAMLコードはユーザーコントロールを作成し、その SetText 依存関係プロパティを初期化します。

<Window x:Class = "WpfApplication3.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:views = "clr-namespace:WpfApplication3"
   Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <views:UserControl1 SetText = "Hellow World"/>
   </Grid>

</Window>

このアプリケーションを実行しましょう。 MainWindowで、ユーザーコントロールの依存関係プロパティがテキストとして正常に使用されたことをすぐに確認できます。

ユーザーの依存関係プロパティ

WPF-ルーティングイベント

  • ルーティングイベント*は、イベントを発生させたオブジェクトだけでなく、要素ツリー内の複数のリスナーでハンドラーを呼び出すことができるイベントのタイプです。 基本的に、Routed EventクラスのインスタンスによってサポートされるCLRイベントです。 WPFイベントシステムに登録されます。 RoutedEventsには、次の3つの主なルーティング戦略があります-
  • 直接イベント
  • バブリングイベント
  • トンネルイベント

直接イベント

直接イベントは、イベントが発生した要素によって発生するWindowsフォームのイベントに似ています。

標準のCLRイベントとは異なり、直接ルーティングイベントはクラス処理をサポートし、カスタムコントロールのスタイル内のイベントセッターおよびイベントトリガーで使用できます。

直接イベントの良い例は、MouseEnterイベントです。

バブリングイベント

バブリングイベントは、イベントが発生した要素で始まります。 次に、ビジュアルツリーを上に移動して、ビジュアルツリーの最上位の要素に移動します。 したがって、WPFでは、最上位の要素はウィンドウである可能性が高いです。

トンネルイベント

要素ツリールートのイベントハンドラーが呼び出され、イベントが発生した要素に到達するまで、イベントはビジュアルツリーを下ってすべての子ノードに移動します。

バブリングイベントとトンネリングイベントの違いは、トンネリングイベントは常にプレビューから始まるということです。

WPFアプリケーションでは、イベントは多くの場合、トンネリング/バブリングのペアとして実装されます。 したがって、プレビューMouseDownがあり、次にMouseDownイベントがあります。

以下は、ボタンと3つのテキストブロックがいくつかのプロパティとイベントで作成されるルーティングイベントの簡単な例です。

<Window x:Class = "WPFRoutedEvents.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "450" Width = "604" ButtonBase.Click  = "Window_Click" >

   <Grid>
      <StackPanel Margin = "20" ButtonBase.Click = "StackPanel_Click">

         <StackPanel Margin = "10">
            <TextBlock Name = "txt1" FontSize = "18" Margin = "5" Text = "This is a TextBlock 1"/>
            <TextBlock Name = "txt2" FontSize = "18" Margin = "5" Text = "This is a TextBlock 2"/>
            <TextBlock Name = "txt3" FontSize = "18" Margin = "5" Text = "This is a TextBlock 3"/>
         </StackPanel>

         <Button Margin = "10" Content = "Click me" Click = "Button_Click" Width = "80"/>
      </StackPanel>
   </Grid>

</Window>

Button、StackPanel、およびWindowのClickイベント実装のC#コードを次に示します。

using System.Windows;

namespace WPFRoutedEvents {
  ///<summary>
     ///Interaction logic for MainWindow.xaml
  ///</summary>

   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();
      }

      private void Button_Click(object sender, RoutedEventArgs e) {
         txt1.Text = "Button is Clicked";
      }

      private void StackPanel_Click(object sender, RoutedEventArgs e) {
         txt2.Text = "Click event is bubbled to Stack Panel";
      }

      private void Window_Click(object sender, RoutedEventArgs e) {
         txt3.Text = "Click event is bubbled to Window";
      }

   }
}

上記のコードをコンパイルして実行すると、次のウィンドウが生成されます-

ルーティングイベント

ボタンをクリックすると、以下に示すように、テキストブロックが更新されます。

ボタンをクリック

特定のレベルでルーティングイベントを停止する場合は、e.Handled = true;を設定する必要があります。

以下に示すように StackPanel_Click イベントを変更しましょう-

private void StackPanel_Click(object sender, RoutedEventArgs e) {
   txt2.Text = "Click event is bubbled to Stack Panel";
   e.Handled = true;
}

ボタンをクリックすると、クリックイベントがウィンドウにルーティングされず、stackpanelで停止し、3 ^ rd ^テキストブロックが更新されないことがわかります。

クリックイベント

カスタムルーティングイベント

  • ルーティングイベントを宣言し、システムコールRegisterRoutedEventで登録します。
  • ルーティング戦略、つまり バブル、トンネル、またはダイレクト。
  • イベントハンドラを提供します。

カスタムルーティングイベントの詳細を理解するための例を見てみましょう。 以下の手順に従ってください-

  • WPFCustomRoutedEventを使用して新しいWPFプロジェクトを作成する
  • ソリューションを右クリックして、[追加]> [新しいアイテム]を選択します。
  • 次のダイアログが開きます。カスタムコントロール(WPF)*を選択し、名前を *MyCustomControl にします。

カスタムルーティングイベント

  • [追加]ボタンをクリックすると、2つの新しいファイル(Themes/Generic.xamlおよびMyCustomControl.cs)がソリューションに追加されます。

次のXAMLコードは、Generic.xamlファイルでカスタムコントロールのスタイルを設定します。

<ResourceDictionary
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local = "clr-namespace:WPFCustomRoutedEvent">

   <Style TargetType = "{x:Type local:MyCustomControl}">
      <Setter Property = "Margin" Value = "50"/>
      <Setter Property = "Template">
         <Setter.Value>
            <ControlTemplate TargetType = "{x:Type local:MyCustomControl}">

               <Border Background = "{TemplateBinding Background}"
                  BorderBrush = "{TemplateBinding BorderBrush}"
                  BorderThickness = "{TemplateBinding BorderThickness}">
                  <Button x:Name = "PART_Button" Content = "Click Me"/>
               </Border>

            </ControlTemplate>
         </Setter.Value>
      </Setter>
   </Style>

</ResourceDictionary>

以下は、カスタムコントロールのカスタムルーティングイベントクリックが作成される* Controlクラス*を継承する* MyCustomControlクラス*のC#コードです。

using System.Windows;
using System.Windows.Controls;

namespace WPFCustomRoutedEvent {

   public class MyCustomControl : Control {

      static MyCustomControl() {
         DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl),
            new FrameworkPropertyMetadata(typeof(MyCustomControl)));
      }

      public override void OnApplyTemplate() {
         base.OnApplyTemplate();

        //demo purpose only, check for previous instances and remove the handler first
         var button  =  GetTemplateChild("PART_Button") as Button;
         if (button ! =  null)
         button.Click + =  Button_Click;
      }

      void Button_Click(object sender, RoutedEventArgs e) {
         RaiseClickEvent();
      }

      public static readonly RoutedEvent ClickEvent  =
         EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble,
         typeof(RoutedEventHandler), typeof(MyCustomControl));

      public event RoutedEventHandler Click {
         add { AddHandler(ClickEvent, value); }
         remove { RemoveHandler(ClickEvent, value); }
      }

      protected virtual void RaiseClickEvent() {
         RoutedEventArgs args = new RoutedEventArgs(MyCustomControl.ClickEvent);
         RaiseEvent(args);
      }

   }
}

ユーザーがクリックするとメッセージボックスを表示するC#のカスタムルーティングイベントの実装を次に示します。

using System.Windows;

namespace WPFCustomRoutedEvent {
  //<summary>
     //Interaction logic for MainWindow.xaml
  //</summary>

   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();
      }

      private void MyCustomControl_Click(object sender, RoutedEventArgs e) {
         MessageBox.Show("It is the custom routed event of your custom control");
      }

   }
}

ルーティングイベントClickを使用してカスタムコントロールを追加するMainWindow.xamlの実装を次に示します。

<Window x:Class = "WPFCustomRoutedEvent.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local = "clr-namespace:WPFCustomRoutedEvent"
   Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <local:MyCustomControl Click = "MyCustomControl_Click"/>
   </Grid>

</Window>

上記のコードをコンパイルして実行すると、カスタムコントロールを含む次のウィンドウが生成されます。

カスタムコントロール

カスタムコントロールをクリックすると、次のメッセージが生成されます。

カスタムcontrol.jpgをクリック

WPF-コントロール

Windows Presentation Foundation(WPF)を使用すると、開発者は視覚的に充実したUIベースのアプリケーションを簡単に構築および作成できます。

  • 他のUIフレームワークの従来のUI要素またはコントロールも、WPFアプリケーションで強化されています。
  • 標準のWPFコントロールはすべて、System.Windows.Controlsの一部であるツールボックスにあります。
  • これらのコントロールは、XAMLマークアップ言語で作成することもできます。

WPFコントロールの完全な継承階層は次のとおりです-

WPFの階層

次の表には、以降の章で説明するコントロールのリストが含まれています。

Sr. No. Controls & Description
1

Button

ユーザー入力に応答するコントロール

2

Calendar

ユーザーが視覚的なカレンダー表示を使用して日付を選択できるようにするコントロールを表します。

3

CheckBox

ユーザーが選択またはクリアできるコントロール。

4

ComboBox

ユーザーが選択できるアイテムのドロップダウンリスト。

5

ContextMenu

この要素内からユーザーインターフェイス(UI)を介してコンテキストメニューが要求されるたびに表示されるコンテキストメニュー要素を取得または設定します。

6

DataGrid

カスタマイズ可能なグリッドにデータを表示するコントロールを表します。

7

DatePicker

ユーザーが日付を選択できるようにするコントロール。

8

Dialogs

アプリケーションは、ユーザーが重要な情報を収集または表示するのに役立つ追加のウィンドウを表示する場合もあります。

9

GridView

水平方向にスクロールできる行と列のアイテムのコレクションを表示するコントロール。

10

Image

画像を表示するコントロール。

11

Label

フォームにテキストを表示します。 アクセスキーのサポートを提供します。

12

ListBox

ユーザーが選択できるアイテムのインラインリストを表示するコントロール。

13

Menus

コマンドおよびイベントハンドラーに関連付けられた要素を階層的に整理できるWindowsメニューコントロールを表します。

14

PasswordBox

パスワードを入力するためのコントロール。

15

Popup

アプリケーションウィンドウの境界内で、既存のコンテンツの上にコンテンツを表示します。

16

ProgressBar

バーを表示して進行状況を示すコントロール。

17

RadioButton

ユーザーがオプションのグループから単一のオプションを選択できるようにするコントロール。

18

ScrollViewer

ユーザーがコンテンツをパンおよびズームできるようにするコンテナーコントロール。

19

Slider

Thumbコントロールをトラックに沿って移動することにより、ユーザーが値の範囲から選択できるようにするコントロール。

20

TextBlock

テキストを表示するコントロール。

21

ToggleButton

2つの状態を切り替えることができるボタン。

22

ToolTip

要素の情報を表示するポップアップウィンドウ。

23

Window

最小化/最大化オプション、タイトルバー、境界線、閉じるボタンを提供するルートウィンドウ

24

3rd Party Controls

WPFアプリケーションでサードパーティコントロールを使用します。

これらのすべてのコントロールについて、実装ごとに説明します。

WPF-レイアウト

コントロールのレイアウトは、アプリケーションのユーザビリティにとって非常に重要かつ重要です。 アプリケーションでGUI要素のグループを配置するために使用されます。 レイアウトパネルを選択する際に考慮すべき特定の重要な事項があります-

  • 子要素の位置
  • 子要素のサイズ
  • 重なり合う子要素のレイヤー化

アプリケーションを異なる画面解像度で使用する場合、コントロールの固定ピクセル配置は機能しません。 XAMLは、GUI要素を適切な方法で配置するための豊富な組み込みレイアウトパネルセットを提供します。 最も一般的に使用され、人気のあるレイアウトパネルのいくつかは次のとおりです-

Sr. No. Panels & Description
1

Stack Panel

スタックパネルは、XAMLのシンプルで便利なレイアウトパネルです。 スタックパネルでは、方向プロパティに基づいて、子要素を水平または垂直に1行に配置できます。

2

Wrap Panel

WrapPanelでは、子要素は、方向プロパティに基づいて、左から右、または上から下の順番で配置されます。

3

Dock Panel

DockPanelは、子要素を互いに対して水平方向または垂直方向に配置する領域を定義します。 DockPanelでは、 Dock プロパティを使用して、子要素を上、下、右、左、および中央に簡単にドッキングできます。

4

Canvas Panel

キャンバスパネルは、左、右、上、下などの Canvas を基準にした座標を使用して子要素を明示的に配置できる基本レイアウトパネルです。

5

Grid Panel

グリッドパネルは、行と列で構成される柔軟な領域を提供します。 グリッドでは、子要素を表形式で配置できます。

WPF-レイアウトのネスト

レイアウトのネストとは、別のレイアウト内でレイアウトパネルを使用することです。 グリッド内にスタックパネルを定義します。 この概念は、アプリケーションで複数のレイアウトの利点を活用するために広く使用されています。 次の例では、グリッド内でスタックパネルを使用します。

次のXAMLコードを見てみましょう。

<Window x:Class = "WPFNestingLayouts.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:WPFNestingLayouts"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">

   <Grid Background = "AntiqueWhite">
      <Grid.RowDefinitions>
         <RowDefinition Height = "*"/>
         <RowDefinition Height = "*"/>
         <RowDefinition Height = "*"/>
         <RowDefinition Height = "*"/>
         <RowDefinition Height = "*"/>
      </Grid.RowDefinitions>

      <Grid.ColumnDefinitions>
         <ColumnDefinition Width = "*"/>
      </Grid.ColumnDefinitions>

      <Label Content = "Employee Info" FontSize = "15"
         FontWeight = "Bold" Grid.Column = "0" Grid.Row = "0"/>

      <StackPanel Grid.Column = "0" Grid.Row = "1" Orientation = "Horizontal">
         <Label Content = "Name"  VerticalAlignment = "Center" Width = "70"/>
         <TextBox Name = "txtName" Text = "Muhammad Ali" VerticalAlignment = "Center"
            Width = "200">
         </TextBox>
      </StackPanel>

      <StackPanel Grid.Column = "0" Grid.Row = "2" Orientation = "Horizontal">
         <Label Content = "ID" VerticalAlignment = "Center" Width = "70"/>
         <TextBox Name = "txtCity" Text = "421" VerticalAlignment = "Center"
            Width = "50">
         </TextBox>
      </StackPanel>

      <StackPanel Grid.Column = "0" Grid.Row = "3" Orientation = "Horizontal">
         <Label Content = "Age" VerticalAlignment = "Center" Width = "70"/>
         <TextBox Name = "txtState" Text = "32" VerticalAlignment = "Center"
            Width = "50"></TextBox>
      </StackPanel>

      <StackPanel Grid.Column = "0" Grid.Row = "4" Orientation = "Horizontal">
         <Label Content = "Title" VerticalAlignment = "Center" Width = "70"/>
         <TextBox Name = "txtCountry" Text = "Programmer" VerticalAlignment = "Center"
            Width = "200"></TextBox>
      </StackPanel>

   </Grid>

</Window>

上記のコードをコンパイルして実行すると、次のウィンドウが生成されます。

レイアウトのネストの出力

上記のサンプルコードを実行して、他のネストレイアウトを試すことをお勧めします。

WPF-入力

Windows Presentation Foundation(WPF)は、マウス、キーボード、タッチパネルなどのさまざまなデバイスから入力を取得できるアプリケーションの助けを借りて、強力なAPIを提供します。 この章では、WPFアプリケーションで処理できる次のタイプの入力について説明します-

Sr. No. Inputs & Description
1

Mouse

MouseDown、MouseEnter、MouseLeaveなど、さまざまなタイプのマウス入力があります。

2

Keyboard

KeyDown、KeyUp、TextInputなど、多くのタイプのキーボード入力があります。

3

ContextMenu or RoutedCommands

RoutedCommandsは、よりセマンティックレベルでの入力処理を可能にします。 これらは実際には、新規、開く、コピー、切り取り、保存などの簡単な手順です。

4

Multi Touch

Windows 7以降のバージョンには、複数のタッチセンシティブデバイスから入力を受信する機能があります。 WPFアプリケーションは、タッチが発生したときにイベントを発生させることにより、タッチ入力をマウスやキーボードなどの他の入力として処理することもできます。

WPF-コマンドライン

コマンドライン引数は、ユーザーが実行時にパラメーターまたは値のセットをWPFアプリケーションに渡すことができるメカニズムです。 これらの引数は、外部からアプリケーションを制御するために非常に重要です。たとえば、コマンドプロンプトからWord文書を開きたい場合、このコマンド「 C:\> start winword word1.docx 」を使用すると、 word1.docx ドキュメントを開きます。

コマンドライン引数は、スタートアップ関数で処理されます。 以下は、コマンドライン引数をWPFアプリケーションに渡す方法を示す簡単な例です。 WPFCommandLine という名前の新しいWPFアプリケーションを作成しましょう。

  • ツールボックスからデザインウィンドウに1つのテキストボックスをドラッグします。
  • この例では、コマンドラインパラメーターとしてtxtファイルのパスをアプリケーションに渡します。
  • プログラムは、txtファイルを読み取り、テキストボックスにすべてのテキストを書き込みます。
  • 次のXAMLコードはテキストボックスを作成し、いくつかのプロパティで初期化します。
<Window x:Class = "WPFCommandLine.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:WPFCommandLine"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525">

   <Grid>
      <TextBox x:Name = "textBox" HorizontalAlignment = "Left"
         Height = "180" Margin = "100" TextWrapping = "Wrap"
         VerticalAlignment = "Top" Width = "300"/>
   </Grid>

</Window>
  • 次に示すように、App.xamlファイルでStartupイベントをサブスクライブします。
<Application x:Class = "WPFCommandLine.App"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local = "clr-namespace:WPFCommandLine"
   StartupUri = "MainWindow.xaml" Startup = "app_Startup">

   <Application.Resources>

   </Application.Resources>

</Application>
  • 以下に示すのは、コマンドライン引数を取得するApp.xaml.csのapp_Startupイベントの実装です。
using System.Windows;

namespace WPFCommandLine {
  ///<summary>
     ///Interaction logic for App.xaml
  ///</summary>

   public partial class App : Application {
      public static string[] Args;

      void app_Startup(object sender, StartupEventArgs e) {
        //If no command line arguments were provided, don't process them
         if (e.Args.Length == 0) return;

         if (e.Args.Length > 0) {
            Args = e.Args;
         }
      }
   }
}
  • これで、MainWindowクラスで、プログラムはtxtファイルを開き、テキストボックスにすべてのテキストを書き込みます。
  • エラーが見つかった場合、プログラムはテキストボックスにエラーメッセージを表示します。
using System;
using System.IO;
using System.Windows;

namespace WPFCommandLine {

   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();
         String[] args = App.Args;

         try {
           //Open the text file using a stream reader.
            using (StreamReader sr = new StreamReader(args[0])) {
              //Read the stream to a string, and write
              //the string to the text box
               String line = sr.ReadToEnd();
               textBox.AppendText(line.ToString());
               textBox.AppendText("\n");
            }
         }
         catch (Exception e) {
            textBox.AppendText("The file could not be read:");
            textBox.AppendText("\n");
            textBox.AppendText(e.Message);
         }
      }
   }
}
  • 上記のコードをコンパイルして実行すると、このプログラムにはコマンドライン引数が必要なため、テキストボックスを含む空白のウィンドウが生成されます。 Visual Studioは、コマンドラインパラメーターを使用してアプリケーションを実行する簡単な方法を提供します。
  • ソリューションエクスプローラーでWPFプロジェクトを右クリックしてプロパティを選択すると、次のウィンドウが表示されます。

WPFコマンドライン

  • [デバッグ]オプションを選択し、コマンドライン引数にファイルパスを書き込みます。
  • Test.txtでtxtファイルを作成し、そのファイルにテキストを書き込み、任意の場所に保存します。 この場合、txtファイルは「 D:\ 」ハードドライブに保存されます。
  • プロジェクトの変更を保存し、今すぐアプリケーションをコンパイルして実行します。 プログラムがText.txtファイルから読み取るTextBoxにテキストが表示されます。

コマンドラインの出力

次に、マシン上のファイル名を Test.txt から Test1.txt に変更して、プログラムを再度実行してみます。テキストボックスにエラーメッセージが表示されます。

コマンドラインのエラー出力

上記のコードを実行し、すべての手順に従ってアプリケーションを正常に実行することをお勧めします。

WPF-データバインディング

データバインディングは、Windowsランタイムアプリがデータを表示および操作するためのシンプルで簡単な方法を提供するWPFアプリケーションのメカニズムです。 このメカニズムでは、データの管理はデータの方法から完全に分離されています。

データバインディングにより、ユーザーインターフェイス上のUI要素とデータオブジェクト間のデータフローが可能になります。 バインディングが確立され、データまたはビジネスモデルが変更されると、更新が自動的にUI要素に反映され、その逆も同様です。 標準のデータソースではなく、ページ上の別の要素にバインドすることもできます。

データバインディングには、*片方向データバインディング*と*双方向データバインディング*の2種類があります。

一方向データバインディング

一方向バインディングでは、データはソース(データを保持するオブジェクト)からターゲット(データを表示するオブジェクト)にバインドされます

  • 一方向のデータバインディングを詳細に理解するために簡単な例を見てみましょう。 まず、 WPFDataBinding という名前の新しいWPFプロジェクトを作成します。
  • 次のXAMLコードは、2つのラベル、2つのテキストボックス、および1つのボタンを作成し、それらをいくつかのプロパティで初期化します。
<Window x:Class = "WPFDataBinding.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:WPFDataBinding"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">

   <Grid>

      <Grid.RowDefinitions>
         <RowDefinition Height = "Auto"/>
         <RowDefinition Height = "Auto"/>
         <RowDefinition Height = "*"/>
      </Grid.RowDefinitions>

      <Grid.ColumnDefinitions>
         <ColumnDefinition Width = "Auto"/>
         <ColumnDefinition Width = "200"/>
      </Grid.ColumnDefinitions>

      <Label Name = "nameLabel" Margin = "2">_Name:</Label>

      <TextBox Name = "nameText" Grid.Column = "1" Margin = "2"
         Text = "{Binding Name, Mode = OneWay}"/>

      <Label Name = "ageLabel" Margin = "2" Grid.Row = "1">_Age:</Label>

      <TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin = "2"
         Text = "{Binding Age, Mode = OneWay}"/>

      <StackPanel Grid.Row = "2" Grid.ColumnSpan = "2">
         <Button Content = "_Show..." Click="Button_Click"/>
      </StackPanel>

   </Grid>
</Window>
  • 両方のテキストボックスのテキストプロパティは、以下に示すPersonクラスのクラス変数である「Name」と「Age」にバインドします。
  • Personクラスには、2つの変数 NameAge があり、そのオブジェクトは MainWindow クラスで初期化されます。
  • XAMLコードでは、NameおよびAgeプロパティにバインドしていますが、そのプロパティが属するオブジェクトを選択していません。
  • より簡単な方法は、オブジェクトを DataContext に割り当てることです。このプロパティのプロパティは、 MainWindowconstructor の次のC#コードでバインドします。
using System.Windows;
namespace WPFDataBinding {

   public partial class MainWindow : Window {

      Person person = new Person { Name = "Salman", Age = 26 };

      public MainWindow() {
         InitializeComponent();
         this.DataContext = person;
      }

      private void Button_Click(object sender, RoutedEventArgs e) {
         string message = person.Name + " is " + person.Age;
         MessageBox.Show(message);
      }
   }

   public class Person {

      private string nameValue;

      public string Name {
         get { return nameValue; }
         set { nameValue = value; }
      }

      private double ageValue;

      public double Age {
         get { return ageValue; }

         set {
            if (value != ageValue) {
               ageValue = value;
            }
         }
      }

   }
}
  • このアプリケーションを実行してみましょう。MainWindowで、PersonオブジェクトのNameとAgeに正常にバインドされていることがすぐにわかります。

DataBindingの出力

  • 表示*ボタンを押すと、メッセージボックスに名前と年齢が表示されます。

表示ボタンが押されたとき

ダイアログボックスで名前と年齢を変更しましょう。

DataBindingで行われた変更

[表示]ボタンをクリックすると、同じメッセージが再び表示されます。

同じメッセージを表示

これは、データバインディングモードがXAMLコードで一方向に設定されているためです。 更新されたデータを表示するには、双方向のデータバインディングを理解する必要があります。

双方向のデータバインディング

双方向バインディングでは、ユーザーはユーザーインターフェイスを介してデータを変更し、そのデータをソースで更新できます。 ユーザーがビューを見ているときにソースが変更された場合、ビューを更新する必要があります。

同じ例を取り上げますが、ここでは、XAMLコードでバインディングモードを一方向から双方向に変更します。

<Window x:Class = "WPFDataBinding.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:WPFDataBinding"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">

   <Grid>

      <Grid.RowDefinitions>
         <RowDefinition Height = "Auto"/>
         <RowDefinition Height = "Auto"/>
         <RowDefinition Height = "*"/>
      </Grid.RowDefinitions>

      <Grid.ColumnDefinitions>
         <ColumnDefinition Width = "Auto"/>
         <ColumnDefinition Width = "200"/>
      </Grid.ColumnDefinitions>

      <Label Name = "nameLabel" Margin = "2">_Name:</Label>
      <TextBox Name = "nameText" Grid.Column = "1" Margin = "2"
         Text = "{Binding Name, Mode = TwoWay}"/>
      <Label Name = "ageLabel" Margin = "2" Grid.Row = "1">_Age:</Label>
      <TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin = "2"
         Text = "{Binding Age, Mode = TwoWay}"/>

      <StackPanel Grid.Row = "2" Grid.ColumnSpan = "2">
         <Button Content = "_Show..." Click = "Button_Click"/>
      </StackPanel>

   </Grid>

</Window>

このアプリケーションを再度実行しましょう。

双方向のデータバインディング

それは同じ出力を生成します-

双方向データバインディングの出力

名前と年齢の値を変更しましょう-

双方向の変更

ここで[表示]ボタンをクリックすると、更新されたメッセージが表示されます。

更新された出力

概念をよりよく理解するために、上記のコードを両方のケースで実行することをお勧めします。

WPF-リソース

リソースは通常、複数回使用することが予想されるオブジェクトに関連付けられた定義です。 コントロールまたは現在のウィンドウのデータをローカルに保存する機能、またはアプリケーション全体のデータをグローバルに保存する機能です。

オブジェクトをリソースとして定義すると、別の場所からアクセスできます。 つまり、オブジェクトを再利用できるということです。 リソースはリソースディクショナリで定義され、任意のオブジェクトをリソースとして定義して、共有可能なアセットにすることができます。 XAMLリソースに対して一意のキーが指定され、そのキーを使用して、StaticResourceマークアップ拡張機能を使用して参照できます。

リソースには2つのタイプがあります-

  • StaticResource
  • DynamicResource

StaticResourceはワンタイムルックアップですが、DynamicResourceはデータバインディングのように機能します。 プロパティは特定のリソースキーに関連付けられていることを覚えています。 そのキーに関連付けられたオブジェクトが変更されると、動的リソースはターゲットプロパティを更新します。

SolidColorBrushリソースの簡単なアプリケーションを次に示します。

  • WPFResouces という名前の新しいWPFプロジェクトを作成しましょう。
  • 次のXAMLコードに示すように、2つの四角形をドラッグし、それらのプロパティを設定します。
<Window x:Class = "WPFResources.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:WPFResources"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525">

   <Window.Resources>
      <SolidColorBrush x:Key = "brushResource" Color = "Blue"/>
   </Window.Resources>

   <StackPanel>
      <Rectangle Height = "50" Margin = "20" Fill = "{StaticResource brushResource}"/>
      <Rectangle Height = "50" Margin = "20" Fill = "{DynamicResource brushResource}"/>
      <Button x:Name = "changeResourceButton"
         Content = "_Change Resource" Click = "changeResourceButton_Click"/>
   </StackPanel>

</Window>
  • 上記のXAMLコードでは、1つの四角形にStaticResourceがあり、もう1つの四角形にDynamicResourceがあり、brushResourceの色がBisqueであることがわかります。
  • コードをコンパイルして実行すると、次のMainWindowが生成されます。

リソースのメインウィンドウ

[リソースの変更]ボタンをクリックすると、DynamicResourceを含む四角形の色が赤に変わることがわかります。

リソースの変更

リソース範囲

リソースは*リソースディクショナリ*で定義されますが、リソースディクショナリを定義できる場所は数多くあります。 上記の例では、リソースディクショナリはウィンドウ/ページレベルで定義されています。 リソースが定義されているディクショナリでは、そのリソースの範囲がすぐに制限されます。 スコープ、つまり リソースを使用できる場所は、定義した場所によって異なります。

  • グリッドのリソースディクショナリでリソースを定義すると、そのグリッドとその子要素のみからアクセスできます。
  • ウィンドウ/ページで定義すると、そのウィンドウ/ページのすべての要素からアクセスできます。
  • アプリのルートはApp.xamlリソースディクショナリにあります。 これはアプリケーションのルートであるため、ここで定義されたリソースはアプリケーション全体にスコープされます。

リソースの範囲に関する限り、ほとんどの場合、アプリケーションレベル、ページレベル、およびグリッド、StackPanelなどの特定の要素レベルです。

リソーススコープ

上記のアプリケーションには、ウィンドウ/ページレベルのリソースがあります。

リソース辞書

XAMLアプリのリソースディクショナリは、リソースディクショナリが個別のファイルに保持されることを意味します。 これは、ほぼすべてのXAMLアプリで採用されています。 別のファイルでリソースを定義すると、次の利点があります-

  • リソースディクショナリでのリソースの定義とUI関連のコードの分離。
  • App.xamlなどの個別のファイルですべてのリソースを定義すると、アプリ全体で利用できるようになります。

それでは、別のファイルのリソースディクショナリでリソースをどのように定義するのでしょうか? さて、それは非常に簡単です、次の手順に従ってVisual Studioを介して新しいリソース辞書を追加するだけです-

  • ソリューションで、新しいフォルダーを追加し、 ResourceDictionaries という名前を付けます。
  • このフォルダーを右クリックし、[サブメニュー項目の追加]から[リソースディクショナリ]を選択して、 DictionaryWithBrush.xaml という名前を付けます。

ここで同じ例を取り上げますが、ここではアプリレベルでリソースディクショナリを定義します。 MainWindow.xamlのXAMLコードは次のとおりです-

<Window x:Class = "WPFResources.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:WPFResources"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525">

   <StackPanel>
      <Rectangle Height = "50" Margin = "20" Fill = "{StaticResource brushResource}"/>
      <Rectangle Height = "50" Margin = "20" Fill = "{DynamicResource brushResource}"/>
      <Button x:Name = "changeResourceButton"
         Content = "_Change Resource" Click = "changeResourceButton_Click"/>
   </StackPanel>

</Window>

これはDictionaryWithBrush.xamlの実装です-

<ResourceDictionary xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml">

   <SolidColorBrush x:Key = "brushResource" Color = "Blue"/>
</ResourceDictionary>

これはapp.xamlの実装です-

<Application x:Class="WPFResources.App"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   StartupUri = "MainWindow.xaml">

   <Application.Resources>
      <ResourceDictionary Source = " XAMLResources\ResourceDictionaries\DictionaryWithBrush.xaml"/>
   </Application.Resources>

</Application>

上記のコードをコンパイルして実行すると、次の出力が生成されます-

リソースディクショナリの出力

[リソースの変更]ボタンをクリックすると、四角形の色が赤に変わります。

リソースディクショナリの変更

上記のコードを実行して、いくつかのリソース(背景色など)を試すことをお勧めします。

WPF-テンプレート

テンプレートは、コントロールの全体的な外観と外観を記述します。 各コントロールには、コントロールに外観を与えるデフォルトのテンプレートが関連付けられています。 WPFアプリケーションでは、コントロールの視覚的な動作と視覚的な外観をカスタマイズするときに、独自のテンプレートを簡単に作成できます。

ロジックとテンプレート間の接続は、データバインディングによって実現できます。 *スタイル*と*テンプレート*の主な違いは以下のとおりです-

  • スタイルは、そのコントロールのデフォルトプロパティを持つコントロールの外観のみを変更できます。
  • テンプレートを使用すると、スタイルよりもコントロールの多くの部分にアクセスできます。 コントロールの既存の動作と新しい動作の両方を指定することもできます。

最も一般的に使用されるテンプレートの2種類があります-

  • 制御テンプレート
  • データテンプレート

制御テンプレート

コントロールテンプレートは、コントロールの視覚的な外観を定義します。 UI要素はすべて、何らかの外観と動作を持っています。たとえば、Buttonには外観と動作があります。 クリックイベントまたはマウスホバーイベントは、クリックアンドホバーに応答して発生する動作であり、コントロールテンプレートによって変更できるボタンのデフォルトの外観もあります。

簡単な例を見てみましょう。 2つのボタンを作成し(1つはテンプレート用、もう1つはデフォルトボタン)、それらをいくつかのプロパティで初期化します。

<Window x:Class = "TemplateDemo.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604">

   <Window.Resources>
      <ControlTemplate x:Key = "ButtonTemplate" TargetType = "Button">

         <Grid>
            <Ellipse x:Name = "ButtonEllipse" Height = "100" Width = "150" >
               <Ellipse.Fill>
                  <LinearGradientBrush StartPoint = "0,0.2" EndPoint = "0.2,1.4">
                     <GradientStop Offset = "0" Color = "Red"/>
                     <GradientStop Offset = "1" Color = "Orange"/>
                  </LinearGradientBrush>
               </Ellipse.Fill>
            </Ellipse>

            <ContentPresenter Content = "{TemplateBinding Content}"
               HorizontalAlignment = "Center" VerticalAlignment = "Center"/>
         </Grid>

         <ControlTemplate.Triggers>

            <Trigger Property = "IsMouseOver" Value = "True">
               <Setter TargetName = "ButtonEllipse" Property = "Fill" >
                  <Setter.Value>
                     <LinearGradientBrush StartPoint = "0,0.2" EndPoint = "0.2,1.4">
                        <GradientStop Offset = "0" Color = "YellowGreen"/>
                        <GradientStop Offset = "1" Color = "Gold"/>
                     </LinearGradientBrush>
                  </Setter.Value>
               </Setter>
            </Trigger>

            <Trigger Property = "IsPressed" Value = "True">
               <Setter Property = "RenderTransform">
                  <Setter.Value>
                     <ScaleTransform ScaleX = "0.8" ScaleY = "0.8"
                        CenterX = "0" CenterY = "0" />
                  </Setter.Value>
               </Setter>
               <Setter Property = "RenderTransformOrigin" Value = "0.5,0.5"/>
            </Trigger>

         </ControlTemplate.Triggers>

      </ControlTemplate>
   </Window.Resources>

   <StackPanel>
      <Button Content = "Round Button!"
         Template = "{StaticResource ButtonTemplate}"
         Width = "150" Margin = "50"/>
      <Button Content = "Default Button!" Height = "40"
         Width = "150" Margin = "5"/>
   </StackPanel>

</Window>

上記のコードをコンパイルして実行すると、次のメインウィンドウが表示されます。

コントロールテンプレート

カスタムテンプレートを使用してボタンの上にマウスを移動すると、下図のように色が変わります。

コントロールテンプレートでマウスオーバー

データテンプレート

データテンプレートは、データコレクションの外観と構造を定義および指定します。 任意のUI要素でデータのプレゼンテーションをフォーマットおよび定義する柔軟性を提供します。 主に、ComboBox、ListBoxなどのデータ関連のItemコントロールで使用されます。

 *データテンプレートの概念を理解するために簡単な例を見てみましょう。* WPFDataTemplates *という名前で新しいWPFプロジェクトを作成します。
* 次のXAMLコードでは、ラベルとテキストボックスを保持するリソースとしてデータテンプレートを作成します。 データを表示するボタンとリストボックスもあります。
<Window x:Class = "WPFDataTemplates.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:WPFDataTemplates"
   xmlns:loc = "clr-namespace:WPFDataTemplates"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525">

   <Window.Resources>
      <DataTemplate DataType = "{x:Type loc:Person}">

         <Grid>
            <Grid.RowDefinitions>
               <RowDefinition Height = "Auto"/>
               <RowDefinition Height = "Auto"/>
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
               <ColumnDefinition Width = "Auto"/>
               <ColumnDefinition Width = "200"/>
            </Grid.ColumnDefinitions>

            <Label Name = "nameLabel" Margin = "10"/>
            <TextBox Name = "nameText" Grid.Column = "1" Margin = "10"
               Text = "{Binding Name}"/>
            <Label Name = "ageLabel" Margin = "10" Grid.Row = "1"/>
            <TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin = "10"
               Text = "{Binding Age}"/>
         </Grid>

      </DataTemplate>
   </Window.Resources>

   <Grid>
      <Grid.RowDefinitions>
         <RowDefinition Height = "Auto"/>
         <RowDefinition Height = "*"/>
      </Grid.RowDefinitions>

      <ListBox ItemsSource = "{Binding}"/>
      <StackPanel Grid.Row = "1" >
         <Button Content = "_Show..." Click = "Button_Click" Width = "80" HorizontalAlignment = "Left" Margin = "10"/>
      </StackPanel>

   </Grid>

</Window>

以下は、C#での実装で、PersonオブジェクトのリストがDataContextに割り当てられ、Personクラスの実装とボタンクリックイベントです。

using System.Collections.Generic;
using System.Windows;

namespace WPFDataTemplates {

   public partial class MainWindow : Window {

      Person src = new Person { Name = "Ali", Age = 27 };
      List<Person> people = new List<Person>();

      public MainWindow() {
         InitializeComponent();
         people.Add(src);
         people.Add(new Person { Name = "Mike", Age = 62 });
         people.Add(new Person { Name = "Brian", Age = 12 });
         this.DataContext = people;
      }

      private void Button_Click(object sender, RoutedEventArgs e) {
         string message = src.Name + " is " + src.Age;
         MessageBox.Show(message);
      }
   }

   public class Person {
      private string nameValue;

      public string Name {
         get { return nameValue; }
         set { nameValue = value; }
      }

      private double ageValue;

      public double Age {
         get { return ageValue; }
         set {
            if (value != ageValue) {
            ageValue = value;
            }
         }
      }
   }

}

上記のコードをコンパイルして実行すると、次のウィンドウが生成されます。 リストには1つのリストが含まれ、リストボックス内の各リストボックス項目には、ラベルボックスとテキストボックスに表示されるPersonクラスオブジェクトデータが含まれます。

データテンプレート

WPF-スタイル

  • スタイルでは、高さ、幅、フォントサイズなど、オブジェクトの既存のプロパティのみを設定できます。
  • コントロールのデフォルトの動作のみを指定できます。
  • 複数のプロパティを単一のスタイルに追加できます。

スタイルは、コントロールのセットに均一な外観または外観を与えるために使用されます。 暗黙的なスタイルは、特定のタイプのすべてのコントロールに外観を適用し、アプリケーションを簡素化するために使用されます。 3つのボタンを想像してください。それらはすべて同じ、同じ幅と高さ、同じフォントサイズ、同じ前景色などに見える必要があります。 これらすべてのプロパティをボタン要素自体に設定できますが、それでもすべてのボタンに問題はありません。 次の図をご覧ください。

スタイル

しかし、実際のアプリケーションでは、通常、まったく同じように見える必要があるこれらの多くがあります。 もちろん、ボタンだけでなく、通常はテキストブロック、テキストボックス、コンボボックスなどが必要になります。 アプリケーション全体で同じように見えます。 確かに、これを達成するためのより良い方法が必要であり、*スタイリング*として知られています。 スタイルは、プロパティ値のセットを複数の要素に適用する便利な方法と考えることができます。 次の図をご覧ください。

スタイルが定義されています

この概念を理解するために簡単な例を見てみましょう。 新しいWPFプロジェクトを作成することから始めます。

  • ツールボックスからデザインウィンドウに3つのボタンをドラッグします。
  • 次のXAMLコードは3つのボタンを作成し、それらをいくつかのプロパティで初期化します。
<Window x:Class = "WPFStyle.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: WPFStyle"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">

   <StackPanel>
      <Button Content = "Button1" Height = "30" Width = "80"
         Foreground = "Blue" FontSize = "12" Margin = "10"/>
      <Button Content = "Button2" Height = "30" Width = "80"
         Foreground = "Blue" FontSize = "12" Margin = "10"/>
      <Button Content = "Button3" Height = "30" Width = "80"
         Foreground = "Blue" FontSize = "12" Margin = "10"/>
   </StackPanel>

</Window>

上記のコードを見ると、すべてのボタンの高さ、幅、前景色、フォントサイズ、およびマージンプロパティが同じであることがわかります。 これで、上記のコードがコンパイルされ実行されると、次のウィンドウが表示されます。

3つのボタンの出力

次に同じ例を見てみましょうが、今回は style を使用します。

<Window x:Class = "XAMLStyle.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:XAMLStyle"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">

   <Window.Resources>
      <Style x:Key = "myButtonStyle" TargetType = "Button">
         <Setter Property = "Height" Value = "30"/>
         <Setter Property = "Width" Value = "80"/>
         <Setter Property = "Foreground" Value = "Blue"/>
         <Setter Property = "FontSize" Value = "12"/>
         <Setter Property = "Margin" Value = "10"/>
      </Style>
   </Window.Resources>

   <StackPanel>
      <Button Content = "Button1" Style = "{StaticResource myButtonStyle}"/>
      <Button Content = "Button2" Style = "{StaticResource myButtonStyle}"/>
      <Button Content = "Button3" Style="{StaticResource myButtonStyle}"/>
   </StackPanel>

</Window>

スタイルはリソースディクショナリで定義され、各スタイルには一意のキー識別子とターゲットタイプがあります。 <style>内では、スタイルに含まれる各プロパティに対して複数のセッタータグが定義されていることがわかります。

上記の例では、各ボタンのすべての共通プロパティがスタイルで定義され、StaticResourceマークアップ拡張を介してスタイルプロパティを設定することにより、スタイルが一意のキーで各ボタンに割り当てられます。

上記のコードをコンパイルして実行すると、次のウィンドウ(同じ出力)が表示されます。

同じ出力

このようにすることの利点はすぐに明らかになります。そのスタイルの範囲内であればどこでも再利用できます。変更する必要がある場合は、各要素ではなくスタイル定義で一度変更するだけです。

スタイルがどのレベルで定義されているかは、そのスタイルの範囲を即座に制限します。 スコープ、つまり スタイルを使用できる場所は、定義した場所によって異なります。 スタイルは、次のレベルで定義することができます-

Sr.No Levels & Description
1

Control Level

コントロールレベルでのスタイルの定義は、その特定のコントロールにのみ適用できます。 以下に示すのは、ボタンとTextBlockが独自のスタイルを持つコントロールレベルの例です。

2

Layout Level

レイアウトレベルでスタイルを定義すると、そのレイアウトとその子要素のみがスタイルにアクセスできるようになります。

3

Window Level

ウィンドウレベルでスタイルを定義すると、そのウィンドウ上のすべての要素からスタイルにアクセスできるようになります。

4

Application Level

アプリレベルでスタイルを定義すると、アプリケーション全体でスタイルにアクセスできるようになります。 同じ例を取り上げましょう。ただし、ここでは、app.xamlファイルにスタイルを入れて、アプリケーション全体でアクセスできるようにします。

WPF-トリガー

トリガーを使用すると、基本的にプロパティ値を変更したり、プロパティの値に基づいてアクションを実行したりできます。 そのため、新しいコントロールを作成しなくても、コントロールの外観や動作を動的に変更できます。

トリガーは、特定の条件が満たされたときに、特定のプロパティの値を変更するために使用されます。 トリガーは通常、特定のコントロールに適用されるスタイルまたはドキュメントのルートで定義されます。 トリガーには3つのタイプがあります-

  • プロパティトリガー
  • データトリガー
  • イベントトリガー

プロパティトリガー

プロパティトリガーでは、あるプロパティで変更が発生すると、別のプロパティで即時またはアニメーションの変更が行われます。 たとえば、プロパティトリガーを使用して、マウスがボタンの上に移動したときにボタンの外観を変更できます。

次のコード例は、マウスがボタンの上に移動したときにボタンの前景色を変更する方法を示しています。

<Window x:Class = "WPFPropertyTriggers.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604">

   <Window.Resources>
      <Style x:Key = "TriggerStyle" TargetType = "Button">
         <Setter Property = "Foreground" Value = "Blue"/>
         <Style.Triggers>
            <Trigger Property = "IsMouseOver" Value = "True">
               <Setter Property = "Foreground" Value = "Green"/>
            </Trigger>
         </Style.Triggers>
      </Style>
   </Window.Resources>

   <Grid>
      <Button Width = "100" Height = "70"
         Style = "{StaticResource TriggerStyle}" Content = "Trigger"/>
   </Grid>

</Window>

上記のコードをコンパイルして実行すると、次のウィンドウが生成されます-

プロパティトリガー

マウスをボタンの上に置くと、前景色が緑色に変わります。

トリガーの色の変更

データトリガー

データトリガーは、バインドされたデータがある条件を満たしたときにいくつかのアクションを実行します。 チェックボックスとテキストブロックがいくつかのプロパティとともに作成される次のXAMLコードを見てみましょう。 チェックボックスをオンにすると、前景色が赤に変わります。

<Window x:Class = "WPFDataTrigger.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "Data Trigger" Height = "350" Width = "604">

   <StackPanel HorizontalAlignment = "Center">
      <CheckBox x:Name = "redColorCheckBox"
         Content = "Set red as foreground color" Margin = "20"/>

      <TextBlock Name = "txtblock" VerticalAlignment = "Center"
         Text = "Event Trigger" FontSize = "24" Margin = "20">
         <TextBlock.Style>
            <Style>
               <Style.Triggers>
                  <DataTrigger Binding = "{Binding ElementName = redColorCheckBox, Path = IsChecked}"
                     Value = "true">
                     <Setter Property = "TextBlock.Foreground" Value = "Red"/>
                     <Setter Property = "TextBlock.Cursor" Value = "Hand"/>
                  </DataTrigger>
               </Style.Triggers>
            </Style>
         </TextBlock.Style>
      </TextBlock>

   </StackPanel>

</Window>

上記のコードをコンパイルして実行すると、次の出力が生成されます-

データトリガー

チェックボックスをオンにすると、テキストブロックの前景色が赤に変わります。

色の変更

イベントトリガー

イベントトリガーは、特定のイベントが発生したときにいくつかのアクションを実行します。 通常、DoubleAnumatio、ColorAnimationなどのコントロールでアニメーションを実行するために使用されます。 次の例では、単純なボタンを作成します。 クリックイベントが発生すると、ボタンの幅と高さが拡大します。

<Window x:Class = "WPFEventTrigger.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <Button Content = "Click Me" Width = "60" Height = "30">

         <Button.Triggers>
            <EventTrigger RoutedEvent = "Button.Click">
               <EventTrigger.Actions>
                  <BeginStoryboard>
                     <Storyboard>

                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty =
                           "Width" Duration = "0:0:4">
                           <LinearDoubleKeyFrame Value = "60" KeyTime = "0:0:0"/>
                           <LinearDoubleKeyFrame Value = "120" KeyTime = "0:0:1"/>
                           <LinearDoubleKeyFrame Value = "200" KeyTime = "0:0:2"/>
                           <LinearDoubleKeyFrame Value = "300" KeyTime = "0:0:3"/>
                        </DoubleAnimationUsingKeyFrames>

                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty = "Height"
                           Duration = "0:0:4">
                           <LinearDoubleKeyFrame Value = "30" KeyTime = "0:0:0"/>
                           <LinearDoubleKeyFrame Value = "40" KeyTime = "0:0:1"/>
                           <LinearDoubleKeyFrame Value = "80" KeyTime = "0:0:2"/>
                           <LinearDoubleKeyFrame Value = "150" KeyTime = "0:0:3"/>
                        </DoubleAnimationUsingKeyFrames>

                     </Storyboard>
                  </BeginStoryboard>
               </EventTrigger.Actions>
            </EventTrigger>
         </Button.Triggers>

      </Button>
   </Grid>

</Window>

上記のコードをコンパイルして実行すると、次のウィンドウが生成されます-

イベントトリガー

ボタンをクリックすると、両方の次元で拡大し始めることがわかります。

イベントトリガーのボタンをクリック

上記の例をコンパイルして実行し、トリガーを他のプロパティにも適用することをお勧めします。

WPF-デバッグ

これは、予期したとおりに動作しないコードの一部のバグまたは欠陥を識別して修正する体系的なメカニズムです。 あるサブシステムのバグを修正すると別のサブシステムにバグが作成される可能性があるため、サブシステムが密結合している複雑なアプリケーションのデバッグはそれほど簡単ではありません。

C#でのデバッグ

WPFアプリケーションでは、プログラマはC#やXAMLなどの2つの言語を扱います。 C#やC/C ++などの手続き型言語でのデバッグに精通しており、ブレークポイントの使用方法も知っている場合は、アプリケーションのC#部分を簡単にデバッグできます。

C#コードをデバッグする方法を示す簡単な例を見てみましょう。 WPFDebuggingDemo という名前の新しいWPFプロジェクトを作成します。 ツールボックスから4つのラベル、3つのテキストボックス、および1つのボタンをドラッグします。 次のXAMLコードをご覧ください。

<Window x:Class = "WPFDebuggingDemo.Window1"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "Window1" Height = "400" Width = "604">

   <Grid>
      <TextBox Height = "23" Margin = "0,44,169,0" Name = "textBox1"
         VerticalAlignment = "Top" HorizontalAlignment = "Right" Width = "120"/>

      <TextBox Height = "23" Margin = "0,99,169,0" Name = "textBox2"
         VerticalAlignment = "Top" HorizontalAlignment = "Right" Width = "120"/>

      <TextBox HorizontalAlignment = "Right" Margin = "0,153,169,0"
         Name = "textBox3" Width = "120" Height = "23" VerticalAlignment = "Top"/>

      <Label Height = "28" Margin = "117,42,0,0" Name = "label1"
         VerticalAlignment = "Top" HorizontalAlignment = "Left" Width = "120">
         Item 1</Label>

      <Label Height = "28" HorizontalAlignment = "Left"
         Margin = "117,99,0,0" Name = "label2" VerticalAlignment = "Top" Width = "120">
         Item 2</Label>

      <Label HorizontalAlignment = "Left" Margin = "117,153,0,181"
         Name = "label3" Width = "120">Item 3</Label>

      <Button Height = "23" HorizontalAlignment = "Right" Margin = "0,0,214,127"
         Name = "button1" VerticalAlignment = "Bottom" Width = "75"
         Click = "button1_Click">Total</Button>

      <Label Height = "28" HorizontalAlignment = "Right"
         Margin = "0,0,169,66" Name = "label4" VerticalAlignment = "Bottom" Width = "120"/>

   </Grid>

</Window>

以下に、ボタンクリックイベントが実装されるC#コードを示します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

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;

namespace WPFDebuggingDemo {
  ///<summary>
     ///Interaction logic for Window1.xaml
  ///</summary>

   public partial class Window1 : Window {

      public Window1() {
         InitializeComponent();
      }

      private void button1_Click(object sender, RoutedEventArgs e) {

         if (textBox1.Text.Length > 0 && textBox2.Text.Length &gt 0 && textBox2.Text.Length > 0) {
            double total = Convert.ToDouble(textBox1.Text) +
            Convert.ToDouble(textBox2.Text) + Convert.ToDouble(textBox3.Text);
            label4.Content = total.ToString();
         }
         else {
            MessageBox.Show("Enter the value in all field.");
         }
      }
   }
}

上記のコードをコンパイルして実行すると、次のウィンドウが生成されます。 ここで、テキストボックスに値を入力し、[合計]ボタンを押します。 テキストボックスに入力されたすべての値の合計後に合計値を取得します。

デバッグ

実際の値以外の値を入力しようとすると、上記のアプリケーションがクラッシュします。 問題を見つけて解決するには(クラッシュする理由)、ボタンクリックイベントにブレークポイントを挿入できます。

以下に示すように、アイテム1に「abc」と書きましょう。

アイテム1

[合計]ボタンをクリックすると、プログラムがブレークポイントで停止することがわかります。

プログラムがクラッシュしています

次に、カーソルをtextbox1.Textの方向に移動すると、プログラムが abc 値を他の値に追加しようとしていることがわかります。これが、プログラムがクラッシュする理由です。

XAMLでのデバッグ

XAMLで同じ種類のデバッグを期待している場合、他の手続き言語コードのデバッグのようにXAMLコードをまだデバッグできないことを知って驚くでしょう。 XAMLコードでデバッグという言葉を聞いたとき、それはエラーを見つけて見つけることを意味します。

  • データバインディングでは、データは画面に表示されず、理由もわかりません
  • または、問題は複雑なレイアウトに関連しています。
  • または、位置合わせの問題または余白の色、オーバーレイなどの問題 ListBoxやコンボボックスなどの広範なテンプレートを使用します。

XAMLプログラムのデバッグは、通常、バインディングが機能するかどうかを確認するために行います。そして、それが機能していない場合、何が悪いのかをチェックします。 残念ながら、Silverlight以外ではXAMLバインディングにブレークポイントを設定することはできませんが、出力ウィンドウを使用してデータバインディングエラーをチェックすることはできます。 次のXAMLコードを見て、データバインディングのエラーを見つけましょう。

<Window x:Class = "DataBindingOneWay.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <StackPanel Name = "Display">
         <StackPanel Orientation = "Horizontal" Margin = "50, 50, 0, 0">
            <TextBlock Text = "Name: " Margin = "10" Width = "100"/>
            <TextBlock Margin = "10" Width = "100" Text = "{Binding FirstName}"/>
         </StackPanel>

         <StackPanel Orientation = "Horizontal" Margin = "50,0,50,0">
            <TextBlock Text = "Title: " Margin = "10" Width = "100"/>
            <TextBlock Margin = "10" Width = "100" Text = "{Binding Title}"/>
         </StackPanel>

      </StackPanel>
   </Grid>

</Window>

2つのテキストブロックのテキストプロパティは「Name」と「Title」に静的に設定され、他の2つのテキストブロックのテキストプロパティは「FirstName」と「Title」にバインドされますが、クラス変数は以下に示すEmployeeクラスのNameとTitleです。

目的の出力が表示されない場合、このタイプの間違いをどこで見つけることができるかを理解するために、意図的に誤った変数名を記述しました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataBindingOneWay {

   public class Employee {
      public string Name { get; set; }
      public string Title { get; set; }

      public static Employee GetEmployee() {

         var emp = new Employee() {
            Name = "Ali Ahmed", Title = "Developer"
         };

         return emp;
      }
   }
}

C#コードでのMainWindowクラスの実装を次に示します。

using System;
using System.Windows;
using System.Windows.Controls;

namespace DataBindingOneWay {
  ///<summary>
     ///Interaction logic for MainWindow.xaml
  ///</summary>

   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();
         DataContext = Employee.GetEmployee();
      }
   }
}

このアプリケーションを実行してみましょう。MainWindowで、EmployeeオブジェクトのTitleに正常にバインドされたが、名前がバインドされていないことがすぐにわかります。

XAMLでのデバッグ

名前で何が起こったのかを確認するために、大量のログが生成される出力ウィンドウを見てみましょう。

エラーを見つけるのは簡単です。エラーを検索するだけで、「BindingExpression path error: 'FirstName' property not found on 'object' Employe _

System.Windows.Data Error: 40 : BindingExpression path error: 'FirstName'
   property not found on 'object' ''Employee' (HashCode=11611730)'.
   BindingExpression:Path = FirstName; DataItem = 'Employee' (HashCode = 11611730);
   target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

FirstNameはEmployeeクラスのメンバーではないことを明確に示しているため、アプリケーションでこの種の問題を解決するのに役立ちます。

FirstNameを再度Nameに変更すると、目的の出力が表示されます。

XAMLのUIデバッグツール

実行時にXAMLコードを検査するために、Visual Studio 2015でXAMLにUIデバッグツールが導入されました。 これらのツールを使用すると、XAMLコードは実行中のWPFアプリケーションの視覚的なツリーの形式で表示され、ツリー内のさまざまなUI要素プロパティも表示されます。 これらのツールを有効にするには、以下の手順に従ってください。

  • [ツール]メニューに移動し、[ツール]メニューから[オプション]を選択します。
  • 次のダイアログボックスが開きます。

デバッグツール

  • 左側の「デバッグ」項目の下の「一般オプション」に移動します。
  • 強調表示されたオプション、つまり「XAMLのUIデバッグツールを有効にする」にチェックマークを付け、[OK]ボタンをクリックします。

XAMLアプリケーションを実行するか、次のXAMLコードを使用します。

<Window x:Class = "XAMLTestBinding.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604">

   <StackPanel>
      <ComboBox Name = "comboBox"  Margin = "50" Width = "100">
         <ComboBoxItem Content = "Green"/>
         <ComboBoxItem  Content = "Yellow" IsSelected = "True"/>
         <ComboBoxItem Content = "Orange"/>
      </ComboBox>

      <TextBox  Name = "textBox" Margin = "50" Width = "100" Height = "23"
         VerticalAlignment = "Top" Text  =
         "{Binding ElementName = comboBox, Path = SelectedItem.Content, Mode = TwoWay, UpdateSourceTrigger = PropertyChanged}"
         Background = "{Binding ElementName = comboBox, Path = SelectedItem.Content}">
      </TextBox>

   </StackPanel>

</Window>

アプリケーションを実行すると、すべての要素がツリーで表示されるライブビジュアルツリーが表示されます。

ライブビジュアルツリー

このライブビジュアルツリーは、UI要素の場所を理解するための完全なレイアウト構造を示しています。 ただし、このオプションはVisual Studio 2015でのみ使用可能です。 Visual Studioの古いオプションを使用している場合、このツールは使用できませんが、XAML Spy for Visual Studioなど、Visual Studioと統合できる別のツールがあります。 xamlspyからダウンロードできます。

WPF-カスタムコントロール

WPFアプリケーションでは、カスタムコントロールを作成できるため、機能が豊富でカスタマイズ可能なコントロールを非常に簡単に作成できます。 カスタムコントロールは、Microsoftが提供するすべての組み込みコントロールが基準を満たしていない場合、またはサードパーティのコントロールに対して支払いを希望しない場合に使用されます。

この章では、カスタムコントロールを作成する方法を学習します。 カスタムコントロールを確認する前に、まずユーザーコントロールを簡単に確認します。

ユーザー管理

ユーザーコントロールは、さまざまな組み込みコントロールを収集して組み合わせ、再利用可能なXAMLにパッケージ化する方法を提供します。 ユーザーコントロールは、次のシナリオで使用されます-

  • コントロールが既存のコントロールで構成されている場合、つまり、複数の既存のコントロールの単一のコントロールを作成できます。
  • コントロールがテーマのサポートを必要としない場合。 ユーザーコントロールは、複雑なカスタマイズ、コントロールテンプレート、およびスタイル設定が難しいものをサポートしていません。
  • 開発者が、イベントハンドラーのビューとダイレクトコードビハインドのコードビハインドモデルを使用してコントロールを記述する場合。
  • アプリケーション間でコントロールを共有することはありません。

ユーザーコントロールの例に進み、以下の手順に従います。

  • 新しいWPFプロジェクトを作成し、ソリューションを右クリックして、[追加]> [新しいアイテム…​]を選択します。

ユーザーコントロール

  • 次のウィンドウが開きます。 ここで、* User Control(WPF)*を選択し、MyUserControlという名前を付けます。

ユーザーコントロールの新しいアイテム

  • [追加]ボタンをクリックすると、2つの新しいファイル(MyUserControl.xamlおよびMyUserControl.cs)がソリューションに追加されることがわかります。

MyUserControl.xamlファイルのいくつかのプロパティを使用してボタンとテキストボックスが作成されるXAMLコードを次に示します。

<UserControl x:Class = "WPFUserControl.MyUserControl"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
   mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "300">

   <Grid>
      <TextBox Height = "23"
         HorizontalAlignment = "Left"
         Margin = "80,49,0,0" Name = "txtBox"
         VerticalAlignment = "Top" Width = "200"/>

      <Button Content = "Click Me"
         Height = "23" HorizontalAlignment = "Left"
         Margin = "96,88,0,0" Name = "button"
         VerticalAlignment = "Top" Click = "button_Click"/>
   </Grid>

</UserControl>

以下に、テキストボックスを更新するMyUserControl.csファイルのボタンクリックイベントのC#コードを示します。

using System;
using System.Windows;
using System.Windows.Controls;

namespace WPFUserControl {
  ///<summary>
     ///Interaction logic for MyUserControl.xaml
  ///</summary>

   public partial class MyUserControl : UserControl {

      public MyUserControl() {
         InitializeComponent();
      }

      private void button_Click(object sender, RoutedEventArgs e) {
         txtBox.Text = "You have just clicked the button";
      }
   }
}

次に、ユーザーコントロールを追加するMainWindow.xamlの実装を示します。

<Window x:Class = "XAMLUserControl.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:control = "clr-namespace:WPFUserControl"
   Title = "MainWindow" Height = "350" Width = "525">

   <Grid>
      <control:MyUserControl/>
   </Grid>

</Window>

上記のコードをコンパイルして実行すると、次のウィンドウが生成されます。

ユーザーコントロールの出力

[クリックしてください]ボタンをクリックすると、テキストボックス内のテキストが更新されます。

ユーザーコントロールでクリックされたボタン

カスタムコントロール

カスタムコントロールは、generic.xamlで通常定義される独自のスタイルとテンプレートを提供するクラスです。 カスタムコントロールは、次のシナリオで使用されます-

  • コントロールが存在せず、ゼロから作成する必要がある場合。
  • 特定のシナリオに合わせてプロパティまたは機能を追加して、既存のコントロールに機能を拡張または追加する場合。
  • コントロールがテーマとスタイリングをサポートする必要がある場合。
  • コントロールをアプリケーション間で共有する場合。

カスタムコントロールの仕組みを理解するための例を見てみましょう。 新しいWPFプロジェクトを作成し、ソリューションを右クリックして、[追加]> [新しいアイテム…​]を選択します。

カスタムコントロール

次のウィンドウが開きます。 ここで、* Custom Control(WPF)を選択し、 *MyCustomControl という名前を付けます。

新しいアイテムを追加

[追加]ボタンをクリックすると、2つの新しいファイル(Themes/Generic.xamlおよびMyCustomControl.cs)がソリューションに追加されることがわかります。

Generic.xamlファイルのカスタムコントロールにスタイルが設定されているXAMLコードを次に示します。

<ResourceDictionary
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local = "clr-namespace:WPFCustomControls">

   <Style TargetType = "{x:Type local:MyCustomControl}"
      BasedOn = "{StaticResource {x:Type Button}}">
      <Setter Property = "Background" Value = "LightSalmon"/>
      <Setter Property = "Foreground" Value = "Blue"/>
   </Style>

</ResourceDictionary>

ボタンクラスから継承され、コンストラクターでメタデータをオーバーライドするMyCustomControlクラスのC#コードを次に示します。

using System;
using System.Windows;
using System.Windows.Controls;

namespace WPFCustomControls {

   public class MyCustomControl : Button {

      static MyCustomControl() {
         DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new
            FrameworkPropertyMetadata(typeof(MyCustomControl)));
      }

   }
}

テキストブロックのテキストを更新するC#のカスタムコントロールクリックイベントの実装を次に示します。

using System;
using System.Windows;
using System.Windows.Controls;

namespace WPFCustomControls {
  ///<summary>
     ///Interaction logic for MainWindow.xaml
  ///</summary>

   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();
      }

      private void customControl_Click(object sender, RoutedEventArgs e) {
         txtBlock.Text = "You have just click your custom control";
      }

   }
}

カスタムコントロールとTextBlockを追加するMainWindow.xamlの実装を次に示します。

<Window x:Class = "WPFCustomControls.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:control = "clr-namespace:WPFCustomControls"
   Title = "MainWindow" Height = "350" Width = "604">

   <StackPanel>
      <control:MyCustomControl x:Name = "customControl"
         Content = "Click Me" Width = "70"
         Margin = "10" Click = "customControl_Click"/>

      <TextBlock Name = "txtBlock"
         Width = "250" Height = "30"/>
   </StackPanel>

</Window>

上記のコードをコンパイルして実行すると、カスタマイズされたボタンであるカスタムコントロールを備えた次のウィンドウが生成されます。

コードの出力

カスタマイズされたボタンをクリックすると、テキストブロック内のテキストが更新されていることがわかります。

カスタマイズされたボタン

WPF-例外処理

例外は、プログラムの実行中に発生したエラー条件または予期しない動作です。 例外は多くの理由により発生する可能性があり、それらのいくつかは次のとおりです-

  • コードまたは呼び出したコード(共有ライブラリなど)のエラー、
  • 利用できないオペレーティングシステムリソース、
  • 共通言語ランタイムが遭遇する予期しない条件(検証できないコードなど)

構文

例外には、プログラムのフローをある部分から別の部分に転送する機能があります。 .NETフレームワークでは、例外処理には次の4つのキーワードがあります-

  • try -このブロックでは、プログラムは何らかの例外を発生させる特定の条件を識別します。
  • catch -catchキーワードは、例外のキャッチを示します。 try ブロックの後に1つ以上の catch ブロックが続き、問題を処理するプログラム内の場所で例外ハンドラーで例外をキャッチします。
  • finally -finallyブロックは、例外がスローされるかどうかに関係なく、指定された一連のステートメントを実行するために使用されます。 たとえば、ファイルを開く場合は、例外が発生したかどうかにかかわらず、ファイルを閉じる必要があります。
  • throw -問題が発生すると、プログラムは例外をスローします。 これは、throwキーワードを使用して行われます。

これらの4つのキーワードを使用する構文は次のようになります-

try {
  ///This will still trigger the exception
}
catch (ExceptionClassName e) {
  //error handling code
}
catch (ExceptionClassName e) {
  //error handling code
}
catch (ExceptionClassName e) {
  //error handling code
}
finally {
  //statements to be executed
}

tryブロックがプログラムフローの状況に応じて複数の例外を発生させる可能性がある場合は、複数のcatchステートメントが使用されます。

階層

  • * ApplicationExceptionクラス*-プログラムによって生成される例外をサポートします。 開発者が例外を定義する場合、クラスはこのクラスから派生する必要があります。
  • * SystemExceptionクラス*-定義済みのすべてのランタイムシステム例外の基本クラスです。 次の階層は、ランタイムによって提供される標準の例外を示しています。

階層

次の表に、ランタイムによって提供される標準の例外と、派生クラスを作成する必要がある条件を示します。

Exception type Base type Description
Exception Object Base class for all exceptions.
SystemException Exception Base class for all runtime-generated errors.
IndexOutOfRangeException SystemException Thrown by the runtime only when an array is indexed improperly.
NullReferenceException SystemException Thrown by the runtime only when a null object is referenced.
AccessViolationException SystemException Thrown by the runtime only when invalid memory is accessed.
InvalidOperationException SystemException Thrown by methods when in an invalid state.
ArgumentException SystemException Base class for all argument exceptions.
ArgumentNullException ArgumentException Thrown by methods that do not allow an argument to be null.
ArgumentOutOfRangeException ArgumentException Thrown by methods that verify that arguments are in a given range.
ExternalException SystemException Base class for exceptions that occur or are targeted at environments outside the runtime.
*SEHException * ExternalException Exception encapsulating Win32 structured exception handling information.

概念をよりよく理解するために簡単な例を見てみましょう。* WPFExceptionHandling *という名前の新しいWPFプロジェクトを作成することから始めます。

ツールボックスからデザインウィンドウに1つのテキストボックスをドラッグします。 次のXAMLコードはテキストボックスを作成し、いくつかのプロパティで初期化します。

<Window x:Class = "WPFExceptionHandling.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:WPFExceptionHandling"
   mc:Ignorable = "d"
   Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <TextBox x:Name = "textBox" HorizontalAlignment = "Left"
         Height = "241" Margin = "70,39,0,0" TextWrapping = "Wrap"
         VerticalAlignment = "Top" Width = "453"/>
   </Grid>

</Window>

以下は、C#での例外処理を伴うファイル読み取りです。

using System;
using System.IO;
using System.Windows;

namespace WPFExceptionHandling {

   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();
         ReadFile(0);
      }

      void ReadFile(int index) {
         string path = @"D:\Test.txt";
         StreamReader file = new StreamReader(path);
         char[] buffer = new char[80];

         try {
            file.ReadBlock(buffer, index, buffer.Length);
            string str = new string(buffer);
            str.Trim();
            textBox.Text = str;
         }
         catch (Exception e) {
            MessageBox.Show("Error reading from "+ path + "\nMessage = "+ e.Message);
         }
         finally {
            if (file != null) {
               file.Close();
            }
         }
      }
   }
}

上記のコードをコンパイルして実行すると、次のウィンドウが生成され、テキストボックス内にテキストが表示されます。

例外処理出力

例外が発生した場合、または次のコードのように手動でスローした場合、エラーのあるメッセージボックスが表示されます。

using System;
using System.IO;
using System.Windows;

namespace WPFExceptionHandling {

   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();
         ReadFile(0);
      }

      void ReadFile(int index) {
         string path = @"D:\Test.txt";
         StreamReader file = new StreamReader(path);
         char[] buffer = new char[80];

         try {
            file.ReadBlock(buffer, index, buffer.Length);
            string str = new string(buffer);
            throw new Exception();
            str.Trim();
            textBox.Text = str;
         }
         catch (Exception e) {
            MessageBox.Show("Error reading from "+ path + "\nMessage = "+ e.Message);
         }
         finally {
            if (file != null) {
               file.Close();
            }
         }
      }
   }
}

上記のコードの実行中に例外が発生すると、次のメッセージが表示されます。

例外メッセージ

上記のコードを実行し、その機能を実験することをお勧めします。

WPF-ローカリゼーション

ローカリゼーションとは、アプリケーションがサポートする特定のカルチャに合わせて、アプリケーションリソースをローカライズバージョンに翻訳することです。

アプリケーションを開発し、アプリケーションを1つの言語のみで使用できる場合、顧客の数とビジネスの規模を制限しています。 顧客ベースを増やしてビジネスを拡大したい場合は、製品が利用可能であり、世界中のユーザーにリーチできる必要があります。 製品の費用対効果の高い*ローカライズ*は、より多くの顧客にアプローチするための最良かつ最も経済的な方法の1つです。

WPFでは、ローカライズ可能な最も簡単なソリューションである resx ファイルを使用して、ローカライズ可能なアプリケーションを非常に簡単に作成できます。 それがどのように機能するかを理解するために簡単な例を見てみましょう-

  • WPFLocalization という名前の新しいWPFプロジェクトを作成します。
  • ソリューションエクスプローラーで、Propertiesフォルダーの下にResources.resxファイルが表示されます。

ローカライズ

  • XAMLファイルでアクセスできるように、アクセス修飾子を内部からパブリックに変更します。

WPFローカリゼーションの変更

  • 次に、アプリケーションで使用する次の文字列の名前と値を追加します。

文字列名を追加

リソースの値を変更する

  • デザインウィンドウに移動して、3つのテキストボックス、3つのラベル、3つのボタンをドラッグします。
  • XAMLファイルで、まずリソースをローカライズするために名前空間宣言を追加します_xmlns:p = "clr-namespace:WPFLocalization.Properties" _ 以下に示すように、すべてのコントロールのプロパティを設定します。 この例では、XAMLファイルのウィンドウのラベル、ボタン、タイトルのコンテンツにハードコードされた文字列を使用しません。 .resxファイルで定義されている文字列を使用します。 たとえば、ウィンドウのタイトルには、次のように* .resxファイルで定義されているタイトル文字列を使用します_“ Title = "\ {x:Static p:Resources.Title}"” _
  • コントロールが作成され、さまざまなプロパティで初期化されるXAMLファイルを次に示します。
<Window x:Class = "WPFLocalization.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local = "clr-namespace:WPFLocalization"
   xmlns:p = "clr-namespace:WPFLocalization.Properties"
   Title = "{x:Static p:Resources.Title}" Height = "350" Width = "604">

   <Grid>
      <TextBox x:Name = "textBox" HorizontalAlignment = "Left" Height = "23"
         Margin = "128,45,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Width = "304"/>

      <Label x:Name = "label" Content = "{x:Static p:Resources.Name}"
         HorizontalAlignment = "Left" Margin = "52,45,0,0" VerticalAlignment = "Top" Width = "86"/>

      <TextBox x:Name = "textBox1" HorizontalAlignment = "Left" Height = "23"
         Margin = "128,102,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Width = "304"/>

      <Label x:Name = "label1" Content = "{x:Static p:Resources.Address}"
         HorizontalAlignment = "Left" Margin = "52,102,0,0" VerticalAlignment = "Top" Width = "86"/>

      <TextBox x:Name = "textBox2" HorizontalAlignment = "Left" Height = "23"
         Margin = "128,157,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Width = "80"/>

      <Label x:Name = "label2" Content = "{x:Static p:Resources.Age}"
         HorizontalAlignment = "Left" Margin = "52,157,0,0" VerticalAlignment = "Top" Width = "86"/>

      <Button x:Name = "button" Content = "{x:Static p:Resources.OK_Button}"
         HorizontalAlignment = "Left" Margin = "163,241,0,0" VerticalAlignment = "Top" Width = "75"/>

      <Button x:Name = "button1" Content = "{x:Static p:Resources.Cancel_Button}"
         HorizontalAlignment = "Left" Margin = "282,241,0,0" VerticalAlignment = "Top" Width = "75"/>

      <Button x:Name = "button2" Content = "{x:Static p:Resources.Help_Button}"
         HorizontalAlignment = "Left" Margin = "392,241,0,0" VerticalAlignment = "Top" Width = "75"/>
   </Grid>

 </Window>
  • 上記のコードがコンパイルされ実行されると、異なるコントロールを含む次のウィンドウが表示されます。

ローカライズの例

  • デフォルトでは、プログラムはデフォルトのResources.resxを使用します。 Resources.ru-RU.resxファイルで定義されているロシア語のテキストを表示する場合は、以下に示すように、プログラムがApp.xamlファイルで起動するときにカルチャを明示的に設定する必要があります。
using System.Windows;

namespace WPFLocalization {
  ///<summary>
     ///Interaction logic for App.xaml
  ///</summary>

   public partial class App : Application {

      App() {
         System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("ru-RU");
        //System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en");
      }
   }
}

アプリケーションを実行すると、すべてのテキストがロシア語で表示されます。

アプリケーションの実行

上記のコードを実行し、他のカルチャ用のresxファイルも作成することをお勧めします。

WPF-相互作用

WPFでは、相互作用は、ビューがそのビューにあるコントロールと相互作用する方法を示します。 最も一般的に知られている相互作用は2つのタイプのものです-

  • ふるまい
  • ドラッグアンドドロップ

ふるまい

一部の機能を再利用可能なコンポーネントにカプセル化できるExpression Blend 3で動作が導入されました。 追加の動作を追加するために、これらのコンポーネントをコントロールに添付できます。 ビヘイビアにより、複雑なユーザーインタラクションを簡単に設計できる柔軟性が提供されます。

ControlStoryBoardActionビヘイビアーがコントロールに関連付けられている簡単な例を見てみましょう。

  • WPFBehaviorという名前の新しいWPFプロジェクトを作成します。
  • 次のXAMLコードは、楕円と、楕円の動きを制御する2つのボタンを作成します。
<Window
   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:WPFBehaviors"
   xmlns:i = "http://schemas.microsoft.com/expression/2010/interactivity"
   xmlns:ei = "http://schemas.microsoft.com/expression/2010/interactions"
   x:Class = "WPFBehaviors.MainWindow"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">

   <Window.Resources>
      <Storyboard x:Key = "Storyboard1" RepeatBehavior = "Forever" AutoReverse = "True">

         <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty =
            "(UIElement.RenderTransform).(TransformGroup.Children )[3].(TranslateTransform.X)"
            Storyboard.TargetName = "ellipse">
            <EasingDoubleKeyFrame KeyTime = "0:0:1" Value = "301.524"/>
            <EasingDoubleKeyFrame KeyTime = "0:0:2" Value = "2.909"/>
         </DoubleAnimationUsingKeyFrames>

         <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty =
            "(UIElement.RenderTransform).(TransformGroup.Children )[3].(TranslateTransform.Y)"
            Storyboard.TargetName = "ellipse">
            <EasingDoubleKeyFrame KeyTime = "0:0:1" Value = "-0.485"/>
            <EasingDoubleKeyFrame KeyTime = "0:0:2" Value = "0"/>
         </DoubleAnimationUsingKeyFrames>

         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty = "(ContentControl.Content)"
            Storyboard.TargetName = "button">
            <DiscreteObjectKeyFrame KeyTime = "0" Value = "Play"/>
         </ObjectAnimationUsingKeyFrames>

         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty = "(ContentControl.Content)"
            Storyboard.TargetName = "button1">
            <DiscreteObjectKeyFrame KeyTime = "0" Value = "Stop"/>
            <DiscreteObjectKeyFrame KeyTime = "0:0:2" Value = "Stop"/>
         </ObjectAnimationUsingKeyFrames>
      </Storyboard>
   </Window.Resources>

   <Window.Triggers>
      <EventTrigger RoutedEvent = "FrameworkElement.Loaded">
         <BeginStoryboard Storyboard = "{StaticResource Storyboard1}"/>
      </EventTrigger>
   </Window.Triggers>

   <Grid>
      <Ellipse x:Name = "ellipse" Fill = "#FFAAAAC5" HorizontalAlignment = "Left"
         Height = "50.901" Margin = "49.324,70.922,0,0" Stroke = "Black"
         VerticalAlignment = "Top" Width = "73.684" RenderTransformOrigin = "0.5,0.5">
         <Ellipse.RenderTransform>
            <TransformGroup>
               <ScaleTransform/>
               <SkewTransform/>
               <RotateTransform/>
               <TranslateTransform/>
            </TransformGroup>
         </Ellipse.RenderTransform>
      </Ellipse>

      <Button x:Name = "button" Content = "Play" HorizontalAlignment = "Left" Height = "24.238"
         Margin = "63.867,0,0,92.953" VerticalAlignment = "Bottom" Width = "74.654">
         <i:Interaction.Triggers>
            <i:EventTrigger EventName = "Click">
               <ei:ControlStoryboardAction Storyboard = "{StaticResource Storyboard1}"/>
            </i:EventTrigger>
         </i:Interaction.Triggers>
      </Button>

      <Button x:Name = "button1" Content = "Stop" HorizontalAlignment = "Left" Height = "24.239"
         Margin = "160.82,0,0,93.922" VerticalAlignment = "Bottom" Width = "75.138">
         <i:Interaction.Triggers>
            <i:EventTrigger EventName = "Click">
               <ei:ControlStoryboardAction ControlStoryboardOption = "Stop"
                  Storyboard = "{StaticResource Storyboard1}"/>
            </i:EventTrigger>
         </i:Interaction.Triggers>
      </Button>

   </Grid>
</Window>

上記のコードをコンパイルして実行すると、楕円と2つのボタンを含む次のウィンドウが生成されます。

インタラクション出力

再生ボタンを押すと、左から右へ移動し始め、元の位置に戻ります。 停止ボタンは、楕円の移動を停止します。

移動が停止しました

ドラッグアンドドロップ

ユーザーインターフェイスでのドラッグアンドドロップにより、アプリケーションの効率と生産性を大幅に向上させることができます。 実装が難しいと人々が考えるため、ドラッグアンドドロップ機能が使用されるアプリケーションはほとんどありません。 ドラッグアンドドロップ機能を扱うのはある程度困難ですが、WPFでは、非常に簡単に処理できます。

それがどのように機能するかを理解するために簡単な例を取り上げましょう。 ある長方形から別の長方形に色をドラッグアンドドロップできるアプリケーションを作成します。

  • WPFDragAndDropという名前の新しいWPFプロジェクトを作成します。
  • 5つの四角形をデザインウィンドウにドラッグし、次のXAMLファイルに示すようにプロパティを設定します。
<Window x:Class = "WPFDragAndDrop.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:WPFDragAndDrop"
   mc:Ignorable = "d" Title = "MainWindow" Height = "402.551" Width = "604">

   <Grid>
      <Rectangle Name = "Target" Fill = "AliceBlue" HorizontalAlignment = "Left"
         Height = "345" Margin = "10,10,0,0" Stroke = "Black"
         VerticalAlignment = "Top" Width = "387" AllowDrop = "True" Drop = "Target_Drop"/>

      <Rectangle Fill = "Beige" HorizontalAlignment = "Left" Height = "65"
         Margin = "402,10,0,0" Stroke = "Black" VerticalAlignment = "Top"
         Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/>

      <Rectangle Fill = "LightBlue" HorizontalAlignment = "Left" Height = "65"
         Margin = "402,80,0,0" Stroke = "Black" VerticalAlignment = "Top"
         Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/>

      <Rectangle Fill = "LightCoral" HorizontalAlignment = "Left" Height = "65"
         Margin = "402,150,0,0" Stroke = "Black" VerticalAlignment = "Top"
         Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/>

      <Rectangle Fill = "LightGray" HorizontalAlignment = "Left" Height = "65"
         Margin = "402,220,0,0" Stroke = "Black" VerticalAlignment = "Top"
         Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/>

      <Rectangle Fill = "OliveDrab" HorizontalAlignment = "Left" Height = "65"
         Margin = "402,290,0,-7" Stroke = "Black" VerticalAlignment = "Top"
         Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/>
   </Grid>

</Window>
  • 最初の長方形はターゲット長方形であるため、ユーザーは他の長方形からターゲット長方形に色をドラッグできます。
  • 以下に、ドラッグアンドドロップ用のC#でのイベントの実装を示します。
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WPFDragAndDrop {
  ///<summary>
     ///Interaction logic for MainWindow.xaml
  ///</summary>

   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();
      }

      private void Rect_MLButtonDown(object sender, MouseButtonEventArgs e) {
         Rectangle rc = sender as Rectangle;
         DataObject data = new DataObject(rc.Fill);
         DragDrop.DoDragDrop(rc, data,DragDropEffects.Move);
      }

      private void Target_Drop(object sender, DragEventArgs e) {
         SolidColorBrush scb = (SolidColorBrush)e.Data.GetData(typeof(SolidColorBrush));
         Target.Fill = scb;
      }
   }
}

アプリケーションを実行すると、次のウィンドウが生成されます。

色のドラッグアンドドロップ

右側の四角形から色をドラッグし、左側の大きな四角形にドロップすると、その効果がすぐにわかります。

4番目の1つを右側からドラッグします。

色のドラッグアンドドロップ

ターゲット四角形の色が変更されていることがわかります。 上記のコードを実行し、その機能を実験することをお勧めします。

WPF-2Dグラフィックス

WPFは、アプリケーションの要件に応じて拡張できる幅広い2Dグラフィックスを提供します。 WPFは、グラフィカルコンテンツの描画に使用されるDrawingオブジェクトとShapeオブジェクトの両方をサポートしています。

形状と描画

  • ShapeクラスはFrameworkElementクラスから派生し、Shapeオブジェクトはパネルおよびほとんどのコントロール内で使用できます。
  • WPFは、Ellipse、Line、Path、Polygon、Polyline、Rectangleなど、Shapeクラスから派生した基本的な図形オブジェクトを提供します。
  • 一方、描画オブジェクトはFrameworkElementクラスから派生したものではなく、より軽量な実装を提供します。
  • 描画オブジェクトは、Shapeオブジェクトに比べて簡単です。 パフォーマンス特性も向上しています。

さまざまな形状オブジェクトの使用方法を理解するために簡単な例を見てみましょう。

  • WPF2DGraphics という名前の新しいWPFプロジェクトを作成します。
  • 次のコードは、さまざまな種類の形状を作成します。
<Window x:Class = "WPF2DGraphics.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:WPF2DGraphics"
   xmlns:PresentationOptions = "http://schemas.microsoft.com/winfx/2006/xaml/present ation/options"
   mc:Ignorable = "PresentationOptions" Title = "MainWindow" Height = "400" Width = "604">

   <StackPanel>
      <Ellipse Width = "100" Height = "60" Name = "sample" Margin = "10">
         <Ellipse.Fill>
            <RadialGradientBrush>
               <GradientStop Offset = "0" Color = "AliceBlue"/>
               <GradientStop Offset = "1" Color = "Gray"/>
               <GradientStop Offset = "2" Color = "Red"/>
            </RadialGradientBrush>
         </Ellipse.Fill>
      </Ellipse>

      <Path Stroke = "Red" StrokeThickness = "5" Data = "M 10,70 L 200,70"
         Height = "42.085" Stretch = "Fill" Margin = "140.598,0,146.581,0"/>
      <Path Stroke = "BlueViolet" StrokeThickness = "5" Data = "M 20,100 A 100,56 42 1 0 200,10"
         Height = "81.316" Stretch = "Fill" Margin = "236.325,0,211.396,0"/>

      <Path Fill = "LightCoral" Margin = "201.424,0,236.325,0"
         Stretch = "Fill" Height = "124.929">
         <Path.Data>
            <PathGeometry>
               <PathFigure StartPoint = "50,0" IsClosed = "True">
                  <LineSegment Point = "100,50"/>
                  <LineSegment Point = "50,100"/>
                  <LineSegment Point = "0,50"/>
               </PathFigure>
            </PathGeometry>
         </Path.Data>
      </Path>

   </StackPanel>

</Window>

上記のコードをコンパイルして実行すると、楕円、直線、円弧、多角形が生成されます。

形状

領域を描画する方法を示す別の例を見てみましょう。

  • WPF2DGraphics1 という名前の新しいWPFプロジェクトを作成します。
  • 次のXAMLコードは、イメージ描画で異なるペイントを行う方法を示しています。
<Window x:Class = "WPF2DGraphics1.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:PresentationOptions = "http://schemas.microsoft.com/winfx/2006/xaml/present ation/options"
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
   mc:Ignorable = "PresentationOptions"
   xmlns:local = "clr-namespace:WPF2DGraphics1" Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <Border BorderBrush = "Gray" BorderThickness = "1"
         HorizontalAlignment = "Left" VerticalAlignment = "Top"
         Margin = "20">

         <Image Stretch = "None">
            <Image.Source>
               <DrawingImage PresentationOptions:Freeze = "True">

                  <DrawingImage.Drawing>
                     <DrawingGroup>
                        <ImageDrawing Rect = "300,100,300,180" ImageSource = "Images\DSC_0104.JPG"/>
                        <ImageDrawing Rect = "0,100,250,100" ImageSource = "Images\DSC_0104.JPG"/>
                        <ImageDrawing Rect = "150,0,25,25" ImageSource = "Images\DSC_0104.JPG"/>
                        <ImageDrawing Rect = "0,0,75,75" ImageSource = "Images\DSC_0104.JPG"/>
                     </DrawingGroup>
                  </DrawingImage.Drawing>

               </DrawingImage>
            </Image.Source>
         </Image>

      </Border>
   </Grid>

</Window>

あなたのアプリケーションを実行すると、次の出力が生成されます-

形状の例

上記のコードを実行して、さらに2D形状と図面を試すことをお勧めします。

WPF-3Dグラフィックス

Windows Presentation Foundation(WPF)は、アプリケーションの要件に応じて、3Dグラフィックスを描画、変換、およびアニメーション化する機能を提供します。 本格的な3Dゲーム開発をサポートしていませんが、ある程度は3Dグラフィックを作成できます。

2Dグラフィックスと3Dグラフィックスを組み合わせることで、豊富なコントロールを作成したり、データの複雑なイラストを提供したり、アプリケーションのインターフェイスのユーザーエクスペリエンスを強化したりすることもできます。 Viewport3D要素は、3DモデルをWPFアプリケーションにホストします。

3Dグラフィックスの使用方法を理解するために簡単な例を見てみましょう。

  • WPF3DGraphics という名前の新しいWPFプロジェクトを作成します。
  • 次のXAMLコードは、3Dジオメトリを使用して2Dオブジェクトを作成する方法を示しています。
<Window x:Class = "WPF3DGraphics.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
   xmlns:local = "clr-namespace:WPF3DGraphics"
   mc:Ignorable = "d" Title = "MainWindow" Height = "500" Width = "604">

   <Grid>
      <Viewport3D>

         <Viewport3D.Camera>
            <PerspectiveCamera Position = "2,0,10" LookDirection = "0.2,0.4,-1"
               FieldOfView = "65" UpDirection = "0,1,0"/>
         </Viewport3D.Camera>

         <ModelVisual3D>
            <ModelVisual3D.Content>
               <Model3DGroup>
                  <AmbientLight Color = "Bisque"/>

                  <GeometryModel3D>
                     <GeometryModel3D.Geometry>
                        <MeshGeometry3D Positions = "0,0,0 0,8,0 10,0,0 8,8,0"
                           Normals = "0,0,1 0,0,1 0,0,1 0,0,1" TriangleIndices = "0,2,1 1,2,3"/>
                     </GeometryModel3D.Geometry>

                     <GeometryModel3D.Material>
                        <DiffuseMaterial Brush = "Bisque"/>
                     </GeometryModel3D.Material>
                  </GeometryModel3D>

               </Model3DGroup>
            </ModelVisual3D.Content>
         </ModelVisual3D>

      </Viewport3D>
   </Grid>

</Window>

上記のコードをコンパイルして実行すると、2Dオブジェクトが3Dで生成されます。

3d_output1

3Dオブジェクトを示す別の例を見てみましょう。

  • WPF3DGraphics1 という名前の新しいWPFプロジェクトを作成します
  • 次のXAMLコードは、3Dオブジェクトとスライダーを作成します。 スライダーを使用して、この3Dオブジェクトを回転できます。
<Window x:Class = "WPF3DGraphics1.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:WPF3DGraphics1"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525">

   <Grid>
      <Viewport3D Name="viewport3D1">

         <Viewport3D.Camera>
            <PerspectiveCamera x:Name = "camMain" Position = "6 5 4" LookDirection = "-6 -5 -4">
            </PerspectiveCamera>
         </Viewport3D.Camera>

         <ModelVisual3D>
            <ModelVisual3D.Content>
               <DirectionalLight x:Name = "dirLightMain" Direction = "-1,-1,-1">
               </DirectionalLight>
            </ModelVisual3D.Content>
         </ModelVisual3D>

         <ModelVisual3D x:Name = "MyModel">
            <ModelVisual3D.Content>
               <GeometryModel3D>

                  <GeometryModel3D.Geometry>
                     <MeshGeometry3D x:Name = "meshMain"
                        Positions = "0 0 0  1 0 0  0 1 0  1 1 0  0 0 1  1 0 1  0 1 1  0 1 1"
                        TriangleIndices = "2 3 1  3 1 0  7 1 3  7 5 1  6 5 7  6 4 5  6 2 0
                        2 0 4  2 7 3  2 6 7  0 1 5  0 5 4">
                     </MeshGeometry3D>
                  </GeometryModel3D.Geometry>

                  <GeometryModel3D.Material>
                     <DiffuseMaterial x:Name = "matDiffuseMain">
                        <DiffuseMaterial.Brush>
                           <SolidColorBrush Color = "Bisque"/>
                        </DiffuseMaterial.Brush>
                     </DiffuseMaterial>
                  </GeometryModel3D.Material>

               </GeometryModel3D>
            </ModelVisual3D.Content>

            <ModelVisual3D.Transform>
               <RotateTransform3D>
                  <RotateTransform3D.Rotation>
                     <AxisAngleRotation3D x:Name = "rotate" Axis = "1 2 1"/>
                  </RotateTransform3D.Rotation>
               </RotateTransform3D>
            </ModelVisual3D.Transform>

         </ModelVisual3D>
      </Viewport3D>

      <Slider Height = "23" HorizontalAlignment = "Left"
         Margin = "145,271,0,0" Name = "slider1"
         VerticalAlignment = "Top" Width = "269"
         Maximum = "360"
         Value = "{Binding ElementName = rotate, Path=Angle}"/>

   </Grid>

</Window>

アプリケーションを実行すると、ウィンドウに3Dオブジェクトとスライダーが生成されます。

3d Output1

スライダーをスライドすると、ウィンドウ上のオブジェクトも回転します。

3d Output2

上記のコードを実行して、さらに3Dジオメトリを試すことをお勧めします。

WPF-マルチメディア

WPFアプリケーションは、 MediaElement を使用してビデオとオーディオをサポートします。 オーディオとビデオをアプリケーションに統合できます。 MediaElementクラスは、Imageクラスと同様に機能します。 メディアに向けるだけでレンダリングされます。 主な違いは、動画であることですが、MP3などの音声のみで動画を含まないファイルをポイントすると、画面に何も表示されずに再生されます。

WPFは、マシンの構成に応じて、すべての種類のビデオ/オーディオ形式をサポートしています。 メディアファイルがMedia Playerを再生する場合、同じマシン上のWPFでも機能します。

アプリケーションにマルチメディアを統合する方法を理解するための例を見てみましょう。

  • WPFMultimedia という名前の新しいWPFプロジェクトを作成します。 *次のXAMLコードは、メディア要素と3つのボタンを作成し、それらをいくつかのプロパティで初期化します。
<Window x:Class = "WPFMultimedia.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:WPFMultimedia"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <StackPanel HorizontalAlignment = "Center" VerticalAlignment = "Center">
         <MediaElement Name = "myMedia" Source = "D:\MicrosoftMVA.mp4"
            LoadedBehavior = "Manual" Width = "591" Height = "274"/>
         <StackPanel Orientation = "Horizontal" Margin = "0,10,0,0">
            <Button Content = "Play" Margin = "0,0,10,0" Padding = "5" Click = "mediaPlay"/>
            <Button Content = "Pause" Margin = "0,0,10,0" Padding = "5" Click = "mediaPause"/>
            <Button x:Name = "muteButt" Content = "Mute" Padding = "5" Click = "mediaMute"/>
         </StackPanel>
      </StackPanel>
   </Grid>

</Window>

以下は、さまざまなボタンのC#でのClickイベントの実装です。

using System;
using System.Windows;

namespace WPFMultimedia {

   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();
         myMedia.Volume = 100;
         myMedia.Play();
      }

      void mediaPlay(Object sender, EventArgs e) {
         myMedia.Play();
      }

      void mediaPause(Object sender, EventArgs e) {
         myMedia.Pause();
      }

      void mediaMute(Object sender, EventArgs e) {

         if (myMedia.Volume == 100) {
            myMedia.Volume = 0;
            muteButt.Content = "Listen";
         }
         else {
            myMedia.Volume = 100;
            muteButt.Content = "Mute";
         }
      }
   }
}

上記のコードをコンパイルして実行すると、次のウィンドウが生成されます。 3つのボタンでビデオを再生し、再生を制御できます。

マルチメディア

ボタンを使用すると、ビデオを一時停止、ミュート、および再生できます。

音声シンセサイザー

WPFには、テキストを音声に変換する機能があります。 このAPIはSystem.Speech名前空間に含まれています。* SpeechSynthesizer *クラスは、テキストを話し言葉に変換します。

簡単な例を見てみましょう。

  • WPFTextToSpeech という名前の新しいWPFプロジェクトを作成します。
  • System.Speechアセンブリが SpeechSynthesizer クラスが動作するための参照として追加する必要があります。
  • [参照]を右クリックし、[参照の追加]を選択します。

WPF Text To Speech

  • Reference Managerダイアログが開きます。 System.Speechチェックボックスをチェックしてください

リファレンスマネージャダイアログ

  • [OK]ボタンをクリックします。 リファレンスでSystem.Speechアセンブリを確認できます。

システム音声

  • 次に、ボタンとテキストボックスをツールボックスからデザインウィンドウにドラッグします。
  • 次のXAMLコードは、ボタンとテキストボックスを作成し、それらをいくつかのプロパティで初期化します。
<Window x:Class = "WPFTextToSpeech.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:WPFTextToSpeech"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">

   <Grid>
      <Button x:Name = "button" Content = "Speak"
         HorizontalAlignment = "Left" Margin = "218,176,0,0"
         VerticalAlignment = "Top" Width = "75"/>

      <TextBox x:Name = "textBox" HorizontalAlignment = "Left"
         Height = "23" Margin = "60,104,0,0" TextWrapping = "Wrap"
         VerticalAlignment = "Top" Width = "418"/>
   </Grid>

</Window>
  • 次に、テキストボックス内のテキストを話し言葉に変換するC#の簡単な実装を示します。
using System.Speech.Synthesis;
using System.Windows;

namespace WPFTextToSpeech {
  ///<summary>
     ///Interaction logic for MainWindow.xaml
  ///</summary>

   public partial class MainWindow : Window {

      public MainWindow() {
         InitializeComponent();
      }

      private void button_Click(object sender, RoutedEventArgs e) {

         if (textBox.Text != "") {
            SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer();
            speechSynthesizer.Speak(textBox.Text);
         }
         else {
            MessageBox.Show("Write some thing in the textbox!");
         }
      }
   }
}

上記のコードをコンパイルして実行すると、次のウィンドウが生成されます。 次に、テキストボックス内に「Hello World」と入力し、「話す」ボタンをクリックします。

マルチメディア出力1

「Hello World」というサウンドが生成されます。 テキストボックスに何も入力しないと、次のメッセージが点滅します。

マルチメディア出力2

上記の例を実行することをお勧めします。