XAML を使用して Windows Presentation Foundation (WPF) アプリを作成する

この本では、XAML 言語の機能を紹介し、XAML を使用して Windows Presentation Foundation (WPF) アプリケーションを作成する方法を示します。

  • XAML とは

XAML は宣言型マークアップ言語です。XAML を .NET Core プログラミング モデルに適用すると、.NET Core アプリの UI を作成するプロセスが簡素化されます。宣言型 XAML マークアップで表示される UI 要素を作成し、部分的なクラス定義を介してマークアップにリンクされている分離コード ファイルを使用して、UI 定義をランタイム ロジックから分離できます。

XAML は、アセンブリで定義された特定のバッキング型のセットを使用して、オブジェクトのインスタンス化を直接表現します。これは、バッキング型システムとの直接的な関係を持たない一般的に解釈される言語である他のほとんどのマークアップ言語とは異なります。XAML は、各関係者がさまざまなツールを使用してアプリケーションの UI とロジックを処理できるワークフローを実装します。

次の例は、UI でボタンを作成する方法を示しています。この例は、XAML が UI プログラミングの一般的な形式をどのように表しているかを示す最初の例です (完全な例ではありません)。

区別に注意してくださいxml xaml yaml wxml。yaml
は Docker の構成言語、xml は Android のフロントエンド UI 言語、wxml は WeChat アプレットのフロントエンド UI 言語です。

XAML の例

<StackPanel>
    <Button Content="Click Me"/>
</StackPanel>

XAML によって実装された WPF インターフェイス
次のインターフェイスはマテリアル デザイン UI フレームワークを使用します
ここに画像の説明を挿入

1.XAML 構文の概要

次のセクションでは、XAML 構文の基本的な形式について説明し、短いマークアップの例を示します。

1.2 XAML オブジェクト要素

オブジェクト要素の構文は、常に左山かっこ (<) で始まります。インスタンスを作成する型の名前が続きます。object 要素タグを完成させるには、閉じ山かっこ (>) で終了します。スラッシュと閉じ山かっこ (/>) を続けてタグを完成させることで、コンテンツなしで自己終了フォームを使用することもできます。

<StackPanel>
    <Button Content="Click Me"/>
</StackPanel>

1.2.1 属性構文 (プロパティ)

オブジェクトのプロパティは、多くの場合、オブジェクトの要素のプロパティとして表現できます。弦。

<Button Background="Blue" Foreground="Red" Content="This is a button"/>

1.2.2 プロパティ要素の構文

次の例は、前の属性構文例と同じプロパティを設定する方法を示していますが、今回は Button のすべてのプロパティに対してプロパティ要素構文を使用しています。

<Button>
    <Button.Background>
        <SolidColorBrush Color="Blue"/>
    </Button.Background>
    <Button.Foreground>
        <SolidColorBrush Color="Red"/>
    </Button.Foreground>
    <Button.Content>
        This is a button
    </Button.Content>
</Button>

1.2.3 コレクションの構文

特定の属性がコレクション型の場合、属性の値内の子要素としてマークアップで宣言されたアイテムはコレクションの一部になります。この場合、サブオブジェクト要素のコレクションが collection プロパティの値として設定されます。

次の例は、GradientStops プロパティの値を設定するための set 構文を示しています。

<LinearGradientBrush>
    <LinearGradientBrush.GradientStops>
        <!-- no explicit new GradientStopCollection, parser knows how to find or create -->
        <GradientStop Offset="0.0" Color="Red" />
        <GradientStop Offset="1.0" Color="Blue" />
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

1.3 XAML コンテンツ プロパティ

XAML は、クラスがそのプロパティの 1 つだけを XAML コンテンツ プロパティとして指定できる言語機能を指定します。オブジェクト (Border) 要素の子要素 ​​(TextBox) は、コンテンツ プロパティ (Width) の値 (300) を設定するために使用されます。つまり、コンテンツ プロパティの場合のみ、XAML マークアップでプロパティを設定するときにプロパティ要素を省略し、マークアップでより直感的な親子フォームを生成できます。

たとえば、Border は Child の content プロパティを指定します。次の 2 つの Border 要素は、同じ方法で処理されます。最初の要素は content 属性構文を使用し、Border.Child 属性要素を省略します。2 番目の要素は、Border.Child を明示的に示しています。

<Border>
    <TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
    <Border.Child>
        <TextBox Width="300"/>
    </Border.Child>
</Border>

XAML 言語の規則として、XAML コンテンツ属性の値は、他の属性要素の前または後に完全に指定する必要があります。たとえば、次のマークアップはコンパイルされません。

<Button>I am a
  <Button.Background>Blue</Button.Background>
  blue button</Button>

以下はコンパイルされます

<Button>
<Button.Background>Blue</Button.Background>
I am a blue button
</Button>

1.3.1 content 属性とコレクション構文の組み合わせ

次の例を考えてみましょう。

<StackPanel>
  <Button>First Button</Button>
  <Button>Second Button</Button>
</StackPanel>

ここで、各 Button は StackPanel の子要素です。これは、2 つの異なる理由で 2 つのマークを省略したシンプルで直感的なマークアップです。

StackPanel.Children プロパティ要素の省略: StackPanel は Panel から派生します。Panel は、Panel.Children を XAML コンテンツ プロパティとして定義します。

UIElementCollection オブジェクト要素が省略されています。Panel.Children プロパティは、IList を実装する UIElementCollection 型を取ります。IList などのコレクションを処理するための XAML 規則に従って、コレクションの要素のマークアップを省略できます。(この場合、UIElementCollection は引数のないコンストラクターを公開しないため、実際にはインスタンス化できません。これが、UIElementCollection オブジェクト要素がコメントアウトされて表示される理由です)。

<StackPanel>
  <StackPanel.Children>
      <Button>First Button</Button>
      <Button>Second Button</Button>
  </StackPanel.Children>
</StackPanel>

1.4 属性構文

1.4.1 イベント (クリック、長押し、選択、フォーカスの取得など)

<Button Click="Button_Click" >Click Me!</Button>

この属性構文の例に加えて、WPF のイベントと XAML に関する詳細があります。たとえば、ここで参照されている ClickHandler が何を表し、どのように定義されているかを確認できます。これについては、この記事の後の「イベントと XAML 分離コード」セクションで説明します。

1.4.2 XAML での大文字と小文字の区別と空白

  • 一般に、XAML では大文字と小文字が区別されます。バッキング タイプを解決するために、CLR が大文字と小文字を区別するのと同じ規則に従って、WPF XAML は大文字と小文字を区別します。
  • XAML 言語のキーワードとプリミティブでも、大文字と小文字が区別されます。値は常に大文字と小文字が区別されるわけではありません。

値が大文字と小文字を区別するかどうかは、値を受け取るプロパティに関連付けられた型コンバーターの動作、またはプロパティ値の型によって異なります。たとえば、ブール型を取るプロパティは、同等のものとして true または True を取ることができますが、これは、文字列をブール型に変換するネイティブ WPF XAML パーサーの型変換が、それらの値を同等のものとして既に許可しているからです。

1.4.3 マークアップ拡張

マークアップ拡張機能は、XAML 言語の概念です。属性構文の値を提供するために使用される場合、中括弧 ({ および }) はマークアップ拡張機能の使用を示します。WPF アプリケーション プログラミングで最も一般的に使用されるマークアップ拡張機能は、Binding (データ バインディング式用) とリソース参照 StaticResource および DynamicResource です。

たとえば、次のマークアップでは、属性構文を使用して Style プロパティの値を設定しています。

<Window x:Class="index.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="100" Width="300">
    <Window.Resources>
        <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
        <Style TargetType="Border" x:Key="PageBackground">
            <Setter Property="BorderBrush" Value="Blue"/>
            <Setter Property="BorderThickness" Value="5" />
        </Style>
    </Window.Resources>
    <Border Style="{ 
        StaticResource PageBackground}">
        <StackPanel>
            <TextBlock Text="Hello" />
        </StackPanel>
    </Border>
</Window>

特に WPF に実装されているすべての XAML マークアップ拡張機能のリファレンス リストについては、「WPF XAML 拡張機能」を参照してください。System.Xaml によって定義され、.NET Core XAML 実装でより広く利用できるマークアップ拡張機能のリファレンス リストについては、「XAML 名前空間 (x:) 言語機能」を参照してください。マークアップ拡張機能の概念の詳細については、「マークアップ拡張機能と WPF XAML」を参照してください。

1.5 型コンバーター

Thickness 構造体は、XAML を使用できる型キャストを持つ型の例です。厚さは、ネストされた四角形の測定値を示し、Margin などのプロパティの値として使用できます。Thickness の型コンバーターを配置すると、Thickness を使用するすべてのプロパティをプロパティとして指定できるため、XAML でより簡単に指定できます。次の例では、型変換と属性構文を使用して Margin の値を指定しています。

<Button Margin="10,20,10,30" Content="Click me"/>

次の例では、代わりに、Thickness オブジェクト要素を含むプロパティ要素構文を介して Margin が設定されます。


<Button Content="Click me">
    <Button.Margin>
        <Thickness Left="10" Top="20" Right="10" Bottom="30"/>
    </Button.Margin>
</Button>

1.6 ルート要素と名前空間

XAML ファイルは、整形式の XML ファイルと有効な XAML ファイルの両方であるために、ルート要素を 1 つだけ持つことができます。一般的な WPF シナリオでは、WPF アプリケーション モデルで目立つルート要素を使用します (たとえば、ページの場合は Window または Page、外部ディクショナリの場合は ResourceDictionary、アプリケーション定義の場合は Application)。

次の例は、Page である WPF ページの一般的な XAML ファイルのルート要素を示しています。

<Page x:Class="index.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="Page1">

</Page>

ルート要素には、属性 xmlns および xmlns:x も含まれます。これらの属性は、どの XAML 名前空間に、マークアップが要素として参照するバッキング型の型定義が含まれているかを XAML プロセッサに示します。xmlns 属性は、既定の XAML 名前空間を明示的に示します。

xmlns 属性は、各 XAML ファイルのルート要素でのみ絶対に必要です。WPF アセンブリから XAML 要素を参照するには、既定の XAML 名前空間を既定の xmlns として宣言するだけです。

1.6.1x: プレフィックス

前のルート要素の例では、プレフィックス x: を使用して XAML 名前空間 http://schemas.microsoft.com/winfx/2006/xaml をマップしていました。

x:Key: ResourceDictionary (または他のフレームワークの同様の辞書概念) 内の各リソースに一意のキーを設定します。x:Key は、おそらく、典型的な WPF アプリケーション マークアップにおけるすべての x: 使用の 90% を占めます。

<Page x:Class="index.Page1"
</Page>

x:Class : XAML ページのコード ビハインドを提供するクラスに、CLR 名前空間とクラス名を指定します。すべての WPF プログラミング モデルでコード ビハインドをサポートするには、このようなクラスが必要です。そのため、リソースがなくても、ほとんどの場合、マップされた x: が表示されます。

x:Name : object 要素を処理した後、ランタイム コードに存在するインスタンスのランタイム オブジェクト名を指定します。ランタイム コードを使用して、初期化された XAML から名前付き要素を検索します。そのような最も一般的なプロパティは FrameworkElement.Name です。

x:Static : XAML 互換プロパティではない静的な値を返す参照を有効にします。

x:Type : タイプ名から Type 参照を構築します。Type を受け取る属性 (Style.TargetType など) を指定するために使用されますが、多くの場合、属性にはネイティブの文字列から型への変換機能があるため、x:Type マークアップ拡張機能の使用はオプションです。

1.6.2 カスタムプレフィックスとカスタムタイプ

独自のカスタム アセンブリ、または PresentationCore、PresentationFramework、および WindowsBase の WPF コア以外のアセンブリについては、アセンブリをカスタム xmlns マッピングの一部として指定できます。このアセンブリの型は、試行している XAML の使用をサポートするために型が正しく実装されている限り、XAML で参照できます。

カスタム プレフィックスが XAML マークアップでどのように機能するかを示す基本的な例を次に示します。

プレフィックス custom はルート要素タグで定義され、アプリケーションにパッケージ化されて出荷される特定のアセンブリにマップされます。このアセンブリには NumericUpDown 型が含まれています。これは、通常の XAML の使用をサポートするだけでなく、WPF XAML コンテンツ モデルのこの特定のポイントに挿入できるクラス継承を使用するために実装されています。このプレフィックスを使用すると、この NumericUpDown コントロールのインスタンスがオブジェクト要素として宣言されるため、XAML パーサーは、型を含む XAML 名前空間を特定できるため、型定義を含むバッキング アセンブリの場所を特定できます。

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary"
    >
  <StackPanel Name="LayoutRoot">
    <custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/>
...
  </StackPanel>
</Page>

Assembly:部品と区別するための付属品またはアセンブリ (コンポーネント)

2 イベント、XAML マークアップ、分離コード

2.1 XAML マークアップ、分離コード

ほとんどの WPF アプリケーションには、XAML マークアップとコード ビハインドの両方が含まれています。

  • XAML マークアップは .xaml ファイルとして記述されます
  • 分離コード ファイルの作成には、Microsoft Visual Basic や C# などの CLR 言語が使用されます。

WPF プログラミングおよびアプリケーション モデルで XAML ファイルをマークアップ コンパイルする場合、XAML ファイルの XAML コード ビハインド ファイルの場所は次のように識別されます。

名前空間とクラスを XAML ルート要素の x:Class 属性として指定します。

これまでに説明した例から、いくつかのボタンを見てきましたが、それらのボタンに関連付けられた論理的な動作はありません。オブジェクト要素に動作を追加するための主なアプリケーションは、要素クラスの既存のイベントを使用し、実行時にそのイベントが発生したときに特定のハンドラーが呼び出されるようにすることです。

  • XAML マークアップでハンドラー名と共にイベント名を指定します。
  • コード ビハインドでハンドラーを実装するコードを定義します。

XAML マークアップ

<Window x:Class="index.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window2" Height="450" Width="800">
    <StackPanel>
        <Button Click="Button_Click">Click me</Button>
    </StackPanel>
</Window>

コードビハインド

private void Button_Click(object sender, RoutedEventArgs e)
{
    
    
    var buttonControl = (Button)e.Source;
    buttonControl.Foreground = Brushes.Red;
}

コード ビハインド ファイルは CLR 名前空間 ExampleNamespace を使用し、その名前空間内で ExamplePage を部分クラスとして宣言していることに注意してください。これは、タグルートで提供される ExampleNamespace.ExamplePage の x:Class 属性値に相当します。WPF マークアップ コンパイラは、ルート要素の型からクラスを派生させることにより、コンパイルする XAML ファイルの部分クラスを作成します。同じ部分クラスを定義する分離コードを提供すると、生成されたコードは、コンパイルされたアプリと同じ名前空間とクラスにマージされます。

別のコード ビハインド ファイルを作成する必要がない場合は、コードを XAML ファイルにインライン化することもできます。ただし、コードのインライン化はあまり一般的ではない方法であり、多くの制限があります。詳細については、「コード ビハインドと WPF の XAML」を参照してください。

2.2 イベントのルーティング

ルーティング イベントは、WPF の基本となる特別なイベント機能です。ルーティング イベントにより、ある要素が別の要素によって発生したイベントを処理できるようになります

名前付き要素

  • 以下の内容は英語から中国語に翻訳されたもので、わかりにくいので、ゆっくり読んでください

既定では、XAML オブジェクト要素には一意の識別子やオブジェクト参照はありません。代わりに、コード内でビュー コンストラクターを呼び出して UI のオブジェクト要素を生成し、コンストラクターを使用して変数を設定して、後でコード内でそのインスタンスを参照できるようにします。

  • コード ビハインドはどのように XAML オブジェクト要素を見つけますか?

XAML は x:Name 属性を定義します。x:Name 属性の値は、任意のオブジェクト要素に設定できます。

コード ビハインドでは、選択された識別子は、構築されたインスタンスを参照するインスタンス変数と同等です。すべての点で、名前付き要素はオブジェクト インスタンスのように機能し (名前はインスタンスを指します)、コード ビハインドは名前付き要素を参照することでアプリ内の実行時の対話を処理できます。
インスタンスと変数の間のこの接続は、WPF XAML マークアップ コンパイラによって実装され、より具体的には、この記事では詳しく説明されていない InitializeComponent などの機能とパターンが関係しています。

WPF フレームワーク レベルの XAML 要素は Name プロパティを継承します。これは、XAML で定義された x:Name 属性と同等です。他の特定のクラスも、x:Name に相当するプロパティ レベルを提供します (多くの場合、Name プロパティとしても定義されます)。一般に、選択した要素/タイプのメンバー テーブルに Name 属性が見つからない場合は、代わりに x:Name を使用できます。x:Name 値は、特定のサブシステムまたは FindName などのユーティリティ メソッドを介して、実行時に使用できる XAML 要素の識別子を提供します。

Android を学習した学生は findViewById() を覚えていますか?
アプレットを学習した学生は findCompent() が
実際には FindName メソッドと同じであることを覚えていますか?

次の例では、StackPanel 要素に Name を設定します。次に、その StackPanel 内の Button のハンドラーが、buttonContainer (名前で設定) へのインスタンス参照によって StackPanel を参照します。

<StackPanel Name="buttonContainer">
    <Button Click="RemoveThis_Click">Click to remove this button</Button>
</StackPanel>
private void RemoveThis_Click(object sender, RoutedEventArgs e)
{
    
    
    var element = (FrameworkElement)e.Source;
    
    if (buttonContainer.Children.Contains(element))
        buttonContainer.Children.Remove(element);
}

XAML 名は、予測可能な範囲内での一意性を強制します。ページのメイン マークアップは、ページのルート要素によって区切られた一意の XAML 名前スコープを表します。

2.3 追加属性と追加イベント

XAML は、プロパティまたはイベントが設定されている要素の型定義にプロパティまたはイベントが存在しない場合でも、特定のプロパティまたはイベントを任意の要素に指定できるようにする言語機能を指定します。この関数のプロパティ版を添付プロパティ、イベント版を添付イベントと呼びます。

概念的には、添付プロパティと添付イベントは、任意の XAML 要素/オブジェクト インスタンスに設定できるグローバル メンバーと考えることができます。ただし、要素/クラスまたはより大きなインフラストラクチャは、付加価値のためのバッキング属性ストアをサポートする必要があります。

XAML の添付プロパティは、通常、属性構文を通じて使用されます。プロパティ構文では、追加のプロパティを ownerType.propertyName の形式で指定できます。

表面的には、これはプロパティ要素の使用法に似ていますが、この場合、指定された ownerType は、添付プロパティが設定されるオブジェクト要素とは常に異なる型です。ownerType この型は、XAML プロセッサが添付プロパティの値を取得または設定するために必要なアクセサー メソッドを提供します。

附加属性的最常见方案是使子元素向其父元素报告属性值。

次の例は、DockPanel.Dock 添付プロパティを示しています。DockPanel クラスは、DockPanel.Dock のアクセサーを定義し、追加のプロパティを持ちます。DockPanel クラスには、その子要素を反復処理し、各要素に DockPanel.Dock 設定値があることを具体的に確認するロジックも含まれています。値が見つかった場合、レイアウト中に子要素を配置するために使用されます。DockPanel.Dock 添付プロパティとこの配置機能を使用することは、実際には DockPanel クラスのエキサイティングな側面です。

<DockPanel>
    <Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
    <Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>

WPF では、ほとんどまたはすべての添付プロパティが依存関係プロパティとしても実装されます。

添付イベントは、ownerType.eventName 属性と同様の構文を使用します。添付されていないイベントと同様に、XAML の添付イベントの属性値は、要素でイベントが処理されるときに呼び出されるハンドラー メソッドの名前を指定します。WPF XAML で添付イベントを使用することは一般的ではありません。

3.ベースタイプ

ベース WPF XAML とその XAML 名前空間は、CLR オブジェクトと XAML のマークアップ要素に対応する型のコレクションです。ただし、すべてのクラスを要素にマップできるわけではありません。ButtonBase などの抽象クラスと特定の非抽象基本クラスは、CLR オブジェクト モデルでの継承に使用されます。基本クラス (抽象クラスを含む) は、XAML 開発にとって依然として重要です。これは、すべての具体的な XAML 要素がその階層内の基本クラスからメンバーを継承するためです。通常、これらのメンバーには、処理可能な要素またはイベントのプロパティとして設定できる属性が含まれています。FrameworkElement は、WPF フレームワーク レベルでの WPF 固有の UI 基本クラスです。UI を設計するときは、さまざまな形状、パネル、デコレータ、またはコントロール クラスを使用しますが、これらはすべて FrameworkElement から派生します。関連する基本クラス FrameworkContentElement は、FrameworkElement の API を意図的にミラーリングする API を使用して、フロー レイアウト表現に適したドキュメント指向の要素をサポートします。要素レベルの属性と CLR オブジェクト モデルの組み合わせにより、具体的な XAML 要素とその基になる型に関係なく、ほとんどの具体的な XAML 要素に設定できる共通のプロパティ セットが提供されます。

4. セキュリティ

XAML は、オブジェクトのインスタンス化と実行を直接表すマークアップ言語です。したがって、XAML で作成された要素は、アプリケーション コードと同様に、システム リソース (ネットワーク アクセス、ファイル システム IO など) と対話できます。また、XAML は、ホスティング アプリと同じようにシステム リソースにアクセスできます。

WPF のコード アクセス セキュリティ (CAS)
.NET Framework とは異なり、WPF for .NET は CAS をサポートしていません。

コードからの XAML の読み込み
XAML を使用して UI 全体を定義できますが、UI の一部を XAML で定義することが適切な場合もあります。この機能は、次の目的で使用できます。

部分的なカスタマイズを有効にします。
UI 情報をローカルに保存します。
ビジネス オブジェクトをモデル化します。


  • 更新日: 2022 年 12 月 1 日 14:33:08

おすすめ

転載: blog.csdn.net/gao511147456/article/details/128130050