マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。

目次

概要

XAMLの書き方(1)の続き。

ビルティング ブロック クラス

WPF / Silverlightは、Windows Formsとは全く異なるUIサブシステムであるが、
類似のビルティング ブロック クラスが使用されているため、よく似たコードでプログラムを記述することができる。

Applicationオブジェクト

WPF / SilverlightにはWindows フォームと同様に Applicationオブジェクトが存在する。

画面の起動

  • WPFでは、ApplicationオブジェクトのStartupUri? 属性に起動時に呼び出されるXAMLを指定する。
  • Applicationオブジェクトはメッセージ ループを構築し、アプリケーションが終了するまでの間、ユーザにイベントを問い合わせる。
  • なお、この処理は、起動時に呼び出されるXAMLのパーシャル クラスに自動生成されるので通常は確認できない。
<Application x:Class="WpfApplication1.App"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  StartupUri="Window1.xaml">
  <Application.Resources></Application.Resources>
</Application>

イベント

Applicationオブジェクトには様々なイベント処理を実装することができる。

  • 開始イベント
    WPF / Silverlightでの共通初期化処理を実装する場合、Application.Startup イベントを使用する。
  • 共通エラー ハンドリング イベント
    WPF / Silverlightでの共通エラー ハンドリング処理を実装する場合、
    Application.DispatcherUnhandledException? イベントで例外をハンドルする。
  • 終了イベント
    WPF / Silverlightでの共通終了処理を実装する場合、Application.Exit イベントを使用する。
  • イベントの実装サンプル
    以下、それぞれのイベントの実装サンプルである。
    • XAML
      <Application x:Class="WpfApplication1.App"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          StartupUri="Window1.xaml"
          Startup="Application_Startup" Exit="Application_Exit"
          DispatcherUnhandledException="Application_DispatcherUnhandledException">
          <Application.Resources></Application.Resources>
      </Application>
    • コード ビハインド
      private void Application_Startup(object sender, StartupEventArgs e) {
        System.Diagnostics.Debug.WriteLine("開始処理");
      }
      
      private void Application_DispatcherUnhandledException(
        object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) {
        System.Diagnostics.Debug.WriteLine("エラー処理");
      }
      
      private void Application_Exit(object sender, ExitEventArgs e) {
        System.Diagnostics.Debug.WriteLine("終了処理");
      }

Application.Propertiesプロパティ

  • WPFではASP.NETなどのWebアプリケーションと同様のSession変数ライクな
    Key - Valueストアとして、Application.Properties プロパティを利用可能である。
  • 以下のサンプルで、任意の個所で(画面間を跨って)
    Application.Propertiesプロパティが取得できることを確認できる。
    • Application.xaml.cs
      • XAML
        private void Application_Startup(object sender, StartupEventArgs e) {
          Application.Current.Properties["Key"] = "Value1";
        }
  • Window1.xaml.cs
    • XAML
      <Window x:Class="WpfApplication1.Window1"
        ・・・
        Loaded="Window_Loaded">
      <Grid>
        <Button Click="Button_Click">ボタン</Button>
      </Grid>
  • コード ビハインド
    private void Window_Loaded(object sender, RoutedEventArgs e) {
      MessageBox.Show((string)Application.Current.Properties["Key"]);
      Application.Current.Properties["Key"] = "Value2";
    }
    
    private void Button_Click(object sender, RoutedEventArgs e) {
      Window2 w2 = new Window2();
      w2.Show();
    }
  • Window2.xaml.cs
    • コード ビハインド
      private void Window_Loaded(object sender, RoutedEventArgs e) {
        MessageBox.Show((string)Application.Current.Properties["Key"]);
      }

Window画面

ウィンドウの起動

WPFではWindows Formsと同様にWindow 画面を、以下のように起動できる(「XBAP」を除く)。

  • モードレス(通常画面)の起動
    モードレス(通常画面)として起動。
    Window2 win2 = new Window2();
    win2.Show();
  • モーダル ダイアログの起動
    モーダル ダイアログとして起動。
    Window2 win2 = new Window2();
    win2.Owner = this;
    win2.ShowDialog();

プロパティ

Windowには、以下のようなプロパティを設定できる。

  • Title
    Window.Title プロパティは、ウィンドウのタイトルを取得 / 設定する。
  • WindowStartUpLocation?
    Window. WindowStartUpLocation? プロパティは、
    ウィンドウ起動時の表示位置を取得 / 設定する。
  • ResizeMode?
    Window. ResizeMode? プロパティは、ウィンドウの
    サイズ変更モードを取得 / 設定する(ResizeMode? 列挙体)。
  • WindowStyle?
    Window. WindowStyle? プロパティは、
    ウィンドウの境界線スタイルを取得 / 設定する。
  • ShowInTaskbar?
    Window. ShowInTaskbar? プロパティは、
    タスクバーのアイコンの表示・非表示を取得 / 設定する。

ナビゲーション フレームワーク

  • WPF / Silverlightでは「ナビゲーション フレームワーク」によりASP.NETなどのWebアプリケーションと同様に、
    WWWブラウザの単一ウィンドウ、複数ページから構成される画面を提供できる。
  • この機能は、「ナビゲーション フレームワーク」のNavigationWindow? / Pageにより提供され、
    ウィザードや、ハイパー テキスト ソリューションに有用である。
  • なお、以下のような機能もサポートされている。
    • WWWブラウザ型の単一ウィンドウ、複数ページから構成される画面を提供
    • WWWブラウザ同様、画面遷移の履歴が残り[進む]・[戻る]操作に対応
    • ハイパーリンクによる画面遷移、HTTPコンテンツの参照をサポート
  • 以下、NavigationWindow? / Pageの使用方法を説明する。

NavigationWindow?画面を作成

  • WPFの場合、初めに、NavigationWindow? (を継承した)画面(ここではNavWindow?クラス)を作成する。
  • なお、NavigationWindow?は、Windowクラスを継承するため、前述のプロパティを設定可能である。
  • コード
    • XAML
      <NavigationWindow x:Class="WpfApplication1.NavWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="NavWindow" Height="300" Width="300">
      </NavigationWindow>
    • コード ビハインド
      public partial class NavWindow : NavigationWindow {
        public NavWindow() {
          InitializeComponent();
        }
      }

NavigationWindow?画面を起動

WPFNavigationWindow?画面を起動する方法について説明する。

  • モードレス(通常画面)
    NavigationWindow?画面をモードレス(通常画面)として起動できる。
    なお、ApplicationオブジェクトのStartupUri?属性から直接起動することもできる。
    NavWindow normalWindow = new NavWindow();
    normalWindow.Show();
  • モーダル ダイアログ
    NavigationWindow?画面をモーダル ダイアログとして起動することもできる。
    NavWindow dialogWindow = new NavWindow(); 
    dialogWindow.Owner = this; 
    bool returnValue = dialogWindow.ShowDialog() ?? false;

Page画面のロード (1)

  • WPFNavigationWindow?画面から、Page 画面をロードする方法について説明する。
  • なお、PageはFrameworkElement?からの派生クラスであって、
    NavigationWindow?・Frame コントロールでのみホスト・ナビゲーションができる。
  • Page 画面をロードする方法
  • Loadedイベントからロード
    NavigationWindow?画面のコード ビハインドのLoadedイベントからPage画面をロードする。
    • XAML
      <NavigationWindow x:Class="WpfApplication1.NavWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="NavWindow" Height="300" Width="300" Loaded="NavigationWindow_Loaded">
      </NavigationWindow>
    • コード ビハインド
      public partial class NavWindow : NavigationWindow {
        public NavWindow() {
          InitializeComponent();
        }
        private void NavigationWindow_Loaded(object sender, RoutedEventArgs e) {
          // Page1 を表示します。
          this.Navigate(new Page1());
        }
      }
  • Sourceプロパティからロード
    NavigationWindow?画面のSourceプロパティに指定してPage画面をロードすることもできる。
    • XAML
      <NavigationWindow x:Class="WpfApplication1.NavWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="NavWindow" Height="300" Width="300" Source="Page1.xaml">
      </NavigationWindow>
  • Frameコントロールからロード
    Page内を複数のFrameに分割し、その中に複数のページをロードすることもできる。
    • XAML
      <StackPanel Orientation="Vertical">
        <Frame Source="Page2.xaml" Navigated="Frame1_Navigated"/>
        <Frame Source="Page3.xaml" Navigated="Frame2_Navigated"/>
      </StackPanel>

Page画面のロード (2)

XBAP」、「Silverlight」では、WindowNavigation? / Windowが使用出来ないため、以下の方法で、直接Page画面をロードする。

  • XBAP
    ApplicationオブジェクトのStartupUri?属性から直接Page画面をロードする。
    <Application x:Class="WpfBrowserApplication1.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StartupUri="Page1.xaml">
        <Application.Resources>
        </Application.Resources>
    </Application>
  • Silverlight
    ApplicationオブジェクトのStartupUri?属性がサポートされないので、
    Application.StartupイベントからPage画面をロードする。
    • XAML
      <Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                   x:Class="SilverlightApplication1.App">
          <Application.Resources> 
          </Application.Resources>
      </Application>
    • コード ビハインド
      public App(){
        this.Startup += this.Application_Startup;
        this.Exit += this.Application_Exit;
        this.UnhandledException += this.Application_UnhandledException;
      
        InitializeComponent();
      }
      
      private void Application_Startup(object sender, StartupEventArgs e) {
        // this.RootVisual = new MainPage(); デフォルトは、ユーザコントロール
        this.RootVisual = new Page1();
      }

なお、「Silverlight」では、
デフォルトの初期画面(Application.RootVisual?)が、ユーザ コントロールとなっているため、
通常、ユーザ コントロールにFrameを追加し、Frameでページ遷移させる方法を取る。

Page画面の画面遷移

WPF / SilverlightにおけるPage画面の画面遷移方法について説明する。

  • Hyperlinkタグによる画面遷移
    • WPFのPage画面では、Hyperlinkタグ使用して、画面遷移できる。
      ※ なお、Hyperlinkタグは、TextBlock?タグなどで囲う必要がある。
      <Hyperlink NavigateUri="Page2.xaml">次のページへ移動します。</Hyperlink>
      <Hyperlink NavigateUri="Page1.xaml">前のページへ移動します。</Hyperlink>
  • SilverlightのPage画面では、HyperlinkButton?タグ使用して、画面遷移できる。
    <HyperlinkButton NavigateUri="/Page2.xaml">次のページへ移動します。</HyperlinkButton>
    <HyperlinkButton NavigateUri="/Page1.xaml">前のページへ移動します。</HyperlinkButton>
  • コードビハインドからの画面遷移
    コード ビハインドからの画面遷移も可能である。
    • WPFの場合は、Page画面を直接生成可能である。
      this.NavigationService.Navigate(new Page2());
    • Silverlightの場合は、Page画面をUriで指定する必要がある。
      • 以下は、相対パス指定:
        this.NavigationService.Navigate(new Uri("/Page2.xaml", UriKind.Relative));
      • 以下は、絶対パス指定:
        this.NavigationService.Navigate(
             new Uri("pack://application:,,,/Page2.xaml", UriKind.Absolute));

Page画面の進む・戻る操作への対応

  • WPF / Silverlightでは、WWWブラウザ同様、進む・戻るボタンが常備されており、
    進む・戻る操作に対応している(Webアプリケーションと同様に、戻った際は、前ページの入力の状態は保持されている)。
  • XBAP」、「Silverlight」については、この進む・戻るボタンは、WWWブラウザのものと統合されている(同じボタンを利用する)。
進む・戻るボタン
  • コードビハインドからの進む・戻る操作
    コードビハインドからは、次の処理で進む・戻る操作に対応できる。
    • 進む
      this.NavigationService.GoForward();
    • 戻る
      this.NavigationService.GoBack();
  • 履歴の管理
    • 進む・戻る操作が行えるということは、画面遷移の履歴を保持しているということである。
      • これを以下のコードで画面遷移のPage履歴を消去できる。
        this.NavigationService.RemoveBackEntry();
      • Page履歴の消去処理を自動化する場合は、NavigationWindow?のNavigatedイベントで実行すると良い。
        private void NavigationWindow_Navigated(object sender, NavigationEventArgs e) {
          this.NavigationService.RemoveBackEntry();
        }
  • XBAP」、「Silverlight」ではNavigationWindow?が存在しないため、FrameのNavigatedイベントで実行する。
    ※ Frameを使用しない場合は、PageのLoadedイベントなどで履歴を消去する。
    private void Frame1_Navigated(object sender, NavigationEventArgs e) {
      if (NavigationService !=null) {
        if (NavigationService.CanGoBack) {
          this.NavigationService.RemoveBackEntry();
        }
      }
    }
    
    private void Frame2_Navigated(object sender, NavigationEventArgs e) {
      if (NavigationService != null) {
        if (NavigationService.CanGoBack) {
          this.NavigationService.RemoveBackEntry();
        }
      }
    }
  • なお、Page履歴の管理はブラック ボックスとなっているため、
    詳細は不明であるが、前Pageに戻った際に入力状態が保持されていることから、
    Page履歴により、ある程度メモリが消費されているものと考える。
    メモリ消費量が拡大するような場合はPage履歴の消去を検討する。

Page画面の進む・戻る操作の注意点

  • [新規画面遷移] → [戻る] → [進む]の一連の操作で、表示されるPageの再初期化が発生するので、
    必要に応じてこれを考慮した実装とするか、[進む]・[戻る]操作を抑止する必要がある。
  • 再初期化とは?
    コンストラクタや、PageのLoadedイベントの処理の実行
    • コンストラクタが実行されるのは、最初のPageのみである。
    • LoadedイベントはすべてのPageで実行される。
  • [進む]・[戻る]操作を抑止する。
    先頭PageでPage.ShowsNavigationUIプロパティをfalseに設定にし、
    以降のPageの[進む]・[戻る]ボタンを非表示にするか、前述の履歴消去で対応する。
  • [進む]・[戻る]ボタンを非表示にする。
    • XAML
      <Page x:Class="WpfApplication1.Page1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Page1" ShowsNavigationUI="false">
  • BackSpace?キーによる[戻る]を抑止
    • [進む]・[戻る]ボタンを非表示にする場合もBackSpace?キーで戻ることができるので、必要に応じてBackSpace?キーを抑止する。
    • また、UI要素にフォーカスの当たっていない状態では、BackSpace?キーを抑止することができないので、
      Page.LoadedイベントなどでPage上の入力UI要素にフォーカスを当てるようにする。
      • XAML
        <Page x:Class="WpfApplication1.Page1"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="Page1" ShowsNavigationUI="false"
          Loaded="Page_Loaded" KeyDown="Page_KeyDown">
          <StackPanel>
            <TextBlock>
              <Hyperlink NavigateUri="Page2.xaml">Page2</Hyperlink>
            </TextBlock>
            <TextBox Name="textBox1"/>
          </StackPanel>
        </Page>
  • コード ビハインド
    public partial class Page1 : Page {
      public Page1() {
        InitializeComponent();
      }
      private void Page_Loaded(object sender, RoutedEventArgs e) {
        this.textBox1.Focus();
      }
      private void Page_KeyDown(object sender, KeyEventArgs e) {
        if (e.Key == Key.Back) e.Handled = true;
      }
    }

その他

NavigationWindow? / Pageのその他のトピック

  • UriMapper?クラス
  • UriMapper? クラスは「Silverlight」専用のコントロールになるが、
    HyperlinkタグのNavigateUri?属性などで使用するPage.xamlへのパスを簡素化することができる。
  • UriMapper?クラスは複数のUriMapping? クラスから構成され、
    UriMapping?クラスのMappedUri?プロパティに実際のPage.xamlへのパス(のパターン)を指定、
    Uriプロパティに簡素化したパス(のパターン)を指定する。
  • 作成したUriMapper?オブジェクトをFrame.UriMapper?プロパティに
    追加することで、Frame内で簡素化したパスを使用することができる。
  • ChildWindow?コントロール
  • ChildWindow? コントロールは、「Silverlight」専用のコントロールであるが、
    Page上に、子ウィンドウ(モーダル ダイアログ相当)を表示できる。
  • Silverlight」アプリケーションのプロジェクトでは、
    ChildWindow?のクラステンプレートが用意されており、
    これを新規作成し、以下のコードでChildWindow?を呼び出すことができる。
  • ChildWindow?は、若干のアニメーションのエフェクトを伴い表示される。
    また、ChildWindow?から、さらに子のChildWindow?を表示させることもできる。
    ChildWindow1 childWindow = new ChildWindow1();
    childWindow.Show();
  • 注意事項
    なお、NavigationWindow? / Pageの使用における注意点は、以下を参照のこと。

Win32ダイアログ

  • WPF / Silverlightは、従来からの種々のWin32ダイアログをサポートしている(一部サポートされないダイアログもある)。
  • このため、WPF / Silverlightアプリケーションであるからと言って、
    「外観や、操作方法の異なる標準ダイアログに慣れる必要がある」・・・といった問題は無い。

メッセージ ボックス

下記のMessageBox?クラスの名前空間は、Windows FormsではなくWPFのものだが、
このMessageBox?クラスのクラス階層を確認するとWPFのアーキテクチャに基づいていないことが確認できる。

コモン ダイアログ ボックス

  • OpenFileDialog? クラス
    • OpenFileDialog?は、部分信頼で実行されている。
    • XBAP」・「Silverlight」でもファイル名を取得できる。
  • SaveFileDialog? クラス
    • SaveFileDialog?は、部分信頼で実行されている。
    • XBAP」・「Silverlight」でもファイルを保存できる。
  • PrintDialog? クラス
    • このクラスの名前空間は、Windows FormsではなくWPFのものだが、
      クラス階層を確認するとWPFのアーキテクチャに基づいていないことが確認できる。
    • Silverlightでは、Printdocument クラス

カスタム ダイアログ ボックス

参考

入力支援

入力支援機能に関する技術要素について説明する。

メニュー・タスクバーとコマンド

  • メニュー・タスクバーと「コマンド」の関連付けも、宣言的プロパティにより実装・カスタマイズ可能。
  • 例えば、以下のXAMLでメニュー・タスクバーと「コマンド」の概要を理解することができ、
    また、メニュー・タスクバーと「コマンド」の関連付けが容易に実装可能であることが分かる。

実装

  • 画面
    メニュー・タスクバーとコマンド
  • XAML
    <Window.CommandBindings>
      <!--ApplicationCommands.Saveのカスタム動作(実行可否、イベント処理)を実装する-->
      <CommandBinding x:Name="SaveCommand"
        Command="ApplicationCommands.Save"
        CanExecute="SaveCommand_CanExecute"
        Executed="SaveCommand_Executed"/>
      <!--ApplicationCommands.Closeのカスタム動作(実行可否、イベント処理)を実装する-->
      <CommandBinding x:Name="CloseCommand"
        Command="ApplicationCommands.Close"
        CanExecute="CloseCommand_CanExecute"
        Executed="CloseCommand_Executed"/>
    </Window.CommandBindings>
    
    <DockPanel>
      <Menu DockPanel.Dock="Top">
        <MenuItem Header="ファイル(_F)">
          <!--ApplicationCommands.Save → カスタム動作 → CommandBinding-->
          <MenuItem Header="保存(_S)" Command="ApplicationCommands.Save">
            <MenuItem.Icon><Image Source=".\icons\save.png"/></MenuItem.Icon>
          </MenuItem>
          <Separator/>
          <!--ApplicationCommands.Close → カスタム動作 → CommandBinding-->
          <!--MenuItem Header="終了(_X)" Command="ApplicationCommands.Close"-->
          <!--ApplicationCommands.Close → カスタム動作 → カスタムイベント-->
          <MenuItem Name="Exit" Click="Exit_Click"  Header="終了(_X)">
            <MenuItem.Icon><Image Source=".\icons\exit.png"/></MenuItem.Icon>
          </MenuItem>
        </MenuItem>
        <MenuItem Header="編集(_E)">
          <!--ApplicationCommands.Undo → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
          <MenuItem Header="元に戻す(_U)" Command="ApplicationCommands.Undo">
            <MenuItem.Icon><Image Source=".\icons\undo.png"/></MenuItem.Icon>
          </MenuItem>
          <!--ApplicationCommands.Redo → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
          <MenuItem Header="やり直し(_R)" Command="ApplicationCommands.Redo">
            <MenuItem.Icon><Image Source=".\icons\redo.png"/></MenuItem.Icon>
          </MenuItem>
          <Separator/>
          <!--ApplicationCommands.Cut → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
          <MenuItem Header="切り取り(_T)" Command="ApplicationCommands.Cut">
            <MenuItem.Icon><Image Source=".\icons\cut.png"/></MenuItem.Icon>
          </MenuItem>
          <!--ApplicationCommands.Copy → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
          <MenuItem Header="コピー(_C)" Command="ApplicationCommands.Copy">
            <MenuItem.Icon><Image Source=".\icons\copy.png"/></MenuItem.Icon>
          </MenuItem>
          <!--ApplicationCommands.Paste → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
          <MenuItem Header="貼り付け(_P)" Command="ApplicationCommands.Paste">
            <MenuItem.Icon><Image Source=".\icons\paste.png"/></MenuItem.Icon>
          </MenuItem>
          <!--ApplicationCommands.Delete → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
          <MenuItem Header="削除(_D)" Command="ApplicationCommands.Delete">
            <MenuItem.Icon><Image Source=".\icons\delete.png"/></MenuItem.Icon>
          </MenuItem>
          <MenuItem Header="配置(_A)">
            <!--EditingCommands.AlignLeft → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="左揃え" Command="EditingCommands.AlignLeft">
              <MenuItem.Icon><Image Source=".\icons\text_align_left.png"/></MenuItem.Icon>
            </MenuItem>
            <!--EditingCommands.AlignCenter → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="中央揃え" Command="EditingCommands.AlignCenter">
              <MenuItem.Icon><Image Source=".\icons\text_align_center.png"/></MenuItem.Icon>
            </MenuItem>
            <!--EditingCommands.AlignRight → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="右揃え" Command="EditingCommands.AlignRight">
              <MenuItem.Icon><Image Source=".\icons\text_align_right.png"/></MenuItem.Icon>
            </MenuItem>
            <!--EditingCommands.AlignJustify → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="両端揃え" Command="EditingCommands.AlignJustify">
              <MenuItem.Icon><Image Source=".\icons\text_align_justify.png"/></MenuItem.Icon>
            </MenuItem>
          </MenuItem>
          <MenuItem Header="スタイル(_S)">
            <!--EditingCommands.ToggleBold → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="太字" Command="EditingCommands.ToggleBold">
              <MenuItem.Icon><Image Source=".\icons\text_bold.png"/></MenuItem.Icon>
            </MenuItem>
            <!--EditingCommands.ToggleItalic → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="斜体" Command="EditingCommands.ToggleItalic">
              <MenuItem.Icon><Image Source=".\icons\text_italic.png"/></MenuItem.Icon>
            </MenuItem>
            <!--EditingCommands.ToggleUnderline → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="下線" Command="EditingCommands.ToggleUnderline">
              <MenuItem.Icon><Image Source=".\icons\text_underline.png"/></MenuItem.Icon>
            </MenuItem>
            <!--EditingCommands.ToggleBullets → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="箇条書き" Command="EditingCommands.ToggleBullets">
              <MenuItem.Icon><Image Source=".\icons\text_list_bullets.png"/></MenuItem.Icon>
            </MenuItem>
            <!--EditingCommands.ToggleNumbering → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="段落番号" Command="EditingCommands.ToggleNumbering">
              <MenuItem.Icon><Image Source=".\icons\text_list_numbers.png"/></MenuItem.Icon>
            </MenuItem>
            <!--EditingCommands.IncreaseIndentation → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="インデントを増やす" Command="EditingCommands.IncreaseIndentation">
              <MenuItem.Icon><Image Source=".\icons\text_indent.png"/></MenuItem.Icon>
            </MenuItem>
            <!--EditingCommands.DecreaseIndentation → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="インデントを減らす" Command="EditingCommands.DecreaseIndentation">
              <MenuItem.Icon><Image Source=".\icons\text_indent_remove.png"/></MenuItem.Icon>
            </MenuItem>
          </MenuItem>
          <MenuItem Header="テキスト(_T)">
            <!--EditingCommands.IncreaseFontSize → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="フォントの拡大" Command="EditingCommands.IncreaseFontSize"/>
            <!--EditingCommands.DecreaseFontSize → フォーカスのあるコントロール(RichTextBox)の既定の動作を実行-->
            <MenuItem Header="フォントの縮小" Command="EditingCommands.DecreaseFontSize"/>
          </MenuItem>
        </MenuItem>
        <MenuItem Header="ヘルプ(_H)">
          <!--RoutedCommandをコードビハインドから自作しカスタム動作(実行可否、イベント処理)を実装する-->
          <MenuItem Header="バージョン情報(_A)" Name="About">
            <MenuItem.Icon><Image Source=".\icons\about.png"/></MenuItem.Icon>
          </MenuItem>
        </MenuItem>
      </Menu>
      <ToolBarTray DockPanel.Dock="Top">
        <ToolBar Header="編集:">
          <Button ToolTip="元に戻す" Command="ApplicationCommands.Undo">
            <Image Source=".\icons\undo.png" Stretch="Fill"/></Button>
          <Button ToolTip="やり直し" Command="ApplicationCommands.Redo">
            <Image Source=".\icons\redo.png" Stretch="Fill"/></Button>
          <Button ToolTip="切り取り" Command="ApplicationCommands.Cut">
            <Image Source=".\icons\cut.png" Stretch="Fill"/></Button>
          <Button ToolTip="コピー" Command="ApplicationCommands.Copy">
            <Image Source=".\icons\copy.png" Stretch="Fill"/></Button>
          <Button ToolTip="貼り付け" Command="ApplicationCommands.Paste">
            <Image Source=".\icons\paste.png" Stretch="Fill"/></Button>
          <Button ToolTip="削除" Command="ApplicationCommands.Delete">
            <Image Source=".\icons\delete.png" Stretch="Fill"/>
          </Button>
        </ToolBar>
        <ToolBar Header="配置:">
          <Button ToolTip="左揃え" Command="EditingCommands.AlignLeft">
            <Image Source=".\icons\text_align_left.png" Stretch="Fill"/></Button>
          <Button ToolTip="中央揃え" Command="EditingCommands.AlignCenter">
            <Image Source=".\icons\text_align_center.png" Stretch="Fill"/></Button>
          <Button ToolTip="右揃え" Command="EditingCommands.AlignRight">
            <Image Source=".\icons\text_align_right.png" Stretch="Fill"/></Button>
          <Button ToolTip="両端揃え" Command="EditingCommands.AlignJustify">
            <Image Source=".\icons\text_align_justify.png" Stretch="Fill"/></Button>
        </ToolBar>
        <ToolBar Header="スタイル:">
          <Button ToolTip="太字" Command="EditingCommands.ToggleBold">
            <Image Source=".\icons\text_bold.png" Stretch="Fill"/></Button>
          <Button ToolTip="斜体" Command="EditingCommands.ToggleItalic">
            <Image Source=".\icons\text_italic.png" Stretch="Fill"/></Button>
          <Button ToolTip="下線" Command="EditingCommands.ToggleUnderline">
            <Image Source=".\icons\text_underline.png" Stretch="Fill"/></Button>
          <Button ToolTip="箇条書き" Command="EditingCommands.ToggleBullets">
            <Image Source=".\icons\text_list_bullets.png" Stretch="Fill"/></Button>
          <Button ToolTip="段落番号" Command="EditingCommands.ToggleNumbering">
            <Image Source=".\icons\text_list_numbers.png" Stretch="fill"/></Button>
          <Button ToolTip="インデントを増やす" Command="EditingCommands.IncreaseIndentation">
            <Image Source=".\icons\text_indent.png" Stretch="Fill"/></Button>
          <Button ToolTip="インデントを減らす" Command="EditingCommands.DecreaseIndentation">
            <Image Source=".\icons\text_indent_remove.png" Stretch="Fill"/></Button>
        </ToolBar>
      </ToolBarTray>
      <RichTextBox DockPanel.Dock="Top" Width="Auto" Height="100"
        IsDocumentEnabled="True" AcceptsTab="True" FontSize="24"/>
      <RichTextBox DockPanel.Dock="Top" Width="Auto" Height="100"
        IsDocumentEnabled="True" AcceptsTab="True" FontSize="24"/>
    </DockPanel>
  • コード ビハインド
    /// <summary>Window1.xaml の相互作用ロジック</summary>
    public partial class Window1 : Window {
      public Window1() {
        InitializeComponent();
    
        // UIElementにRoutedCommandをバインドし、メニューに関連付ける。
        InitRoutedCommands_about();
      }
    
      // AboutCommand(カスタムのRoutedCommand)
      public static readonly RoutedCommand AboutCommand = new RoutedCommand();
    
      private void InitRoutedCommands_about() {
    
        // CommandBindingの生成
        CommandBinding binding = 
          new CommandBinding(AboutCommand, AboutCommand_Executed, AboutCommand_CanExecute);
    
        // UIElementにRoutedCommandをバインド
        this.CommandBindings.Add(binding);
    
        // メニューに関連付け
        About.Command = AboutCommand;
      }
    
      // 【情報メニュー+コマンド】UIElementにRoutedCommandをバインド:カスタム動作(実行可否)
      private void AboutCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) { 
        e.CanExecute = true;
      }
      // 【情報メニュー+コマンド】UIElementにRoutedCommandをバインド:カスタム動作(実行可否)
      private void AboutCommand_Executed(object sender, ExecutedRoutedEventArgs e) {
        // 情報表示処理
      }
    
      // 【保存メニュー+コマンド】UIElementにRoutedCommandをバインド:カスタム動作(実行可否)
      private void SaveCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) { 
        e.CanExecute = true;
      }
      // 【保存メニュー+コマンド】UIElementにRoutedCommandをバインド:カスタム動作(イベント処理)
      private void SaveCommand_Executed(object sender, ExecutedRoutedEventArgs e) {
        // 保存処理
      }
    
      // 【終了メニュー+コマンド】UIElementにRoutedCommandをバインド:カスタム動作(実行可否)
      private void CloseCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) { 
        e.CanExecute = true;
      }
      // 【終了メニュー+コマンド】UIElementにRoutedCommandをバインド:カスタム動作(イベント処理)
      private void CloseCommand_Executed(object sender, ExecutedRoutedEventArgs e) { 
        this.Close();
      }
    
      // 【終了メニュー】メニューのクリックイベントのみの実装で済ます場合。
      private void Exit_Click(object sender, RoutedEventArgs e) { 
        this.Close();
      }
    }

説明

  • メニュー・タスクバーと「コマンド」の関連付け
    • MenuItem?
      • MenuItem?MenuItem? クラス)は入れ子が可能であり、
      • MenuItem?のアクセスキーは、MenuItem?クラスのHeader属性に指定する文字列中に
        「英数字」と設定することで(英数字の先頭文字をアクセスキーとして)容易に設定可能
      • また、MenuItem?からはCommand属性を指定して指定の「Command」を発生させることができる。
  • ToolBarTray?
    • ToolBarTray? には、を格納でき、ToolBar?にはButtonを格納できる。
    • Buttonからは指定の「Command」を発生させることができる。
    • ToolBarTray?内のToolBar?は、実行時にD&Dにて配置を変更できる。
  • Command
    • これらのコントロールから発生させた「Command」は、フォーカスのあるコントロールに受信されるが、
    • CommandTarget?="{Binding ElementName?=要素名}"という記述により、対象のコントロールを明示することもできる。
    • 対象のコントロールは、各種RoutedCommand? クラスのCanExecute?、Executeメソッドが
      発生させるイベントを処理するイベント ハンドラを実装している必要がある。
  • 標準コマンド
  • 標準コマンド(ApplicationCommands?, EditingCommands?, etc. )に対応した処理を実装しているコントロールには、
    • 「コマンド」に対応する処理のUOCは不要であり、既定の処理が実行される。
    • また、「コマンド」には、既定のショートカットも割り当てられている。
  • コントロールの実装する標準コマンド(上記サンプルでは、ApplicationCommands?.Save・Close)の処理をカスタマイズしたい場合、
  • 「コマンド」に対応したイベント ハンドラのUOCをUIElement(上記サンプルでは、Window)に定義・実装する必要がある。
  • 標準コマンドのカスタム処理の定義・実装には、標準コマンド(ApplicationCommands?)をUIElementのCommandBindings?プロパティに追加し、
    ApplicationCommands?.CanExecute?、Executeが発生させるカスタム イベントを処理するイベント ハンドラのUOCをUIElement上に実装する必要がある。
  • また、上記の方式は、カスタム コマンド(RoutedCommand?)に対応したイベント ハンドラのUOCをUIElementに定義・実装する場合にも利用できる。
  • その他にも、以下の標準コマンドがSystem.Windows.Input名前空間に用意されている。
    • ComponentCommands?
    • MediaCommands?
    • NavigationCommands?

参考

  • .NET Frameworkクラス ライブラリ

ツールチップ

  • WPFでは、「ツールチップ」を任意のUIコントロールに設定可能である。
  • これにはFrameworkElement?FrameworkContentElement?ToolTip? プロパティが実装されているためである。

実装

  • 画面
    ツールチップ
  • XAML
    • UserControl?
      <UserControl x:Class="WpfApplication1.UserControl1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Width="250" Height="120">
        <StackPanel>
          <TextBlock Margin="4,4,4,4" Text="タイトル"
            TextWrapping="Wrap" FontWeight="Bold" FontSize="14"/>
          <Path Width="Auto" Height="1" 
            Fill="Black" Stretch="Fill" 
            Stroke="Black" Data="M20,45 L250,45" 
            Margin="4,4,4,4"/>
          <TextBlock Margin="4,4,4,4" Text="説明文" 
            TextWrapping="Wrap"/>
        </StackPanel>
      </UserControl>
  • Window
    <Window x:Class="WpfApplication1.Window1"
      ・・・
        xmlns:my="clr-namespace:WpfApplication1"
      ・・・>
    
      ・・・
    
    <RichTextBox DockPanel.Dock="Top" Width="Auto" Height="100" 
                 IsDocumentEnabled="True" AcceptsTab="True" FontSize="24">
      <RichTextBox.ToolTip>
        <ToolTip>
          <my:UserControl1/>
        </ToolTip>
      </RichTextBox.ToolTip>
    </RichTextBox>

説明

このToolTip?プロパティには、ToolTip?属性に直接文字列で説明文を記述することも可能であるが、
「プロパティ要素構文」を使用して、説明文などの文字列だけではなく、(imageなどの)任意のUI要素も設定可能である。
例えば、以下は、ユーザ コントロールを使用してToolTip?を表示した例である。

参考

IME制御

  • WPF / Silverlightでは、InputMethod? クラスを利用することでIME制御が可能である(XAMLから直接指定することも可能)。
  • ただし、
    • IME2003以外では、IMEのオン・オフの切り替え(ひらがな ⇔ 直接入力)はできるが、
    • 入力モードの切り替え(カタカナ ⇔ 全角英字など)はできないので注意が必要 。
  • 切り替え方法
    • IMEオン・オフ
      • InputMethod?.SetIsInputMethodEnabled?メソッド
      • InputMethod?.Current.ImeState?プロパティ
    • 入力モード
      • InputMethod?.SetPreferredImeConversionMode?メソッド
      • InputMethod?.Current.ImeConversionMode?プロパティ

実装

以下は、IME制御のサンプルである。

  • 画面
    IME制御
  • XAML
    イベント ハンドラでIME制御する方法と、XAMLでIME制御する方法がある。
  • イベント ハンドラでIME制御
    <StackPanel Orientation="Vertical">
      <StackPanel Orientation="Horizontal">
        <TextBlock Height="23" Width="80" Text="制御なし:"/>
        <TextBox Name="textBox0" Height="23" Width="120"/>
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <TextBlock Height="23" Text="以下、イベントで制御"/>
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <TextBlock Height="23" Width="80" Text="OFF:"/>
        <TextBox Name="textBox1" Height="23" Width="120"
          GotFocus="textBox1_GotFocus" LostFocus="textBox1_LostFocus"/>
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <TextBlock Height="23" Width="80" Text="ON:"/>
        <TextBox Name="textBox2" Height="23" Width="120"
          GotFocus="textBox2_GotFocus" LostFocus="textBox2_LostFocus"/>
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <TextBlock Height="23" Width="80" Text="全角片仮名:"/>
        <TextBox Name="textBox3" Height="23" Width="120"
          GotFocus="textBox3_GotFocus" LostFocus="textBox3_LostFocus"/>
      </StackPanel>
  • XAMLでIME制御
      <StackPanel Orientation="Horizontal">
        <TextBlock Height="23" Text="以下、XAMLで制御"/>
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <TextBlock Height="23" Width="80" Text="OFF:"/>
        <TextBox Name="textBox4" Height="23" Width="120"
          InputMethod.PreferredImeState="Off"/>
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <TextBlock Height="23" Width="80" Text="ON:"/>
        <TextBox Name="textBox5" Height="23" Width="120"
          InputMethod.PreferredImeState="On"/>
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <TextBlock Height="23" Width="80" Text="半角片仮名:"/>
        <TextBox Name="textBox6" Height="23" Width="120"
          InputMethod.PreferredImeState="On" InputMethod.PreferredImeConversionMode="Native,Fixed,Katakana"/>
      </StackPanel>
    </StackPanel>
  • コード ビハインド
    下記はイベント ハンドラによるIME制御である。
    /// <summary>Window1.xaml の相互作用ロジック</summary>
    public partial class Window1 : Window {
      public Window1() {
        InitializeComponent();
      }
    
      InputMethodState ims = InputMethodState.DoNotCare;
      ImeConversionModeValues imc = ImeConversionModeValues.DoNotCare;
    
      private void textBox1_GotFocus(object sender, RoutedEventArgs e) {
        ims = InputMethod.Current.ImeState;
        InputMethod.Current.ImeState = InputMethodState.Off;
      }
      private void textBox1_LostFocus(object sender, RoutedEventArgs e) {
        InputMethod.Current.ImeState = ims;
      }
    
      private void textBox2_GotFocus(object sender, RoutedEventArgs e) {
        ims = InputMethod.Current.ImeState;
         InputMethod.Current.ImeState = InputMethodState.On;
      }
      private void textBox2_LostFocus(object sender, RoutedEventArgs e) {
        InputMethod.Current.ImeState = ims;
      }
    
      private void textBox3_GotFocus(object sender, RoutedEventArgs e) {
        ims = InputMethod.Current.ImeState;
        imc = InputMethod.Current.ImeConversionMode;
    
        InputMethod.Current.ImeState = InputMethodState.On;
        InputMethod.Current.ImeConversionMode = ImeConversionModeValues.Native
          | ImeConversionModeValues.FullShape | ImeConversionModeValues.Katakana;
      }
      private void textBox3_LostFocus(object sender, RoutedEventArgs e) {
        InputMethod.Current.ImeState = ims;
        InputMethod.Current.ImeConversionMode = imc;
      }
    }

説明

イベント ハンドラでのIME制御の動作は、
以下の点が、XAMLによるIME制御の場合と異なる。

  • GotFocus?LostFocus?イベントを扱っており、
    GotFocus?イベントで現状のIME設定を保存し、
    LostFocus?イベントでIME設定を復元している。
  • このため、入力時のIME設定変更はLostFocus?イベントで無効になる。

参考

デザイナ向け機能

デザイナ向けの技術要素について説明する。

様々なシェイプ

  • Shapeクラスから派生するベクタ グラフィックス描画クラスには、次のものがある。
    • Rectangle クラス
      四角形を描画
  • Ellipse クラス
    楕円を描画
  • Line クラス
    直線を描画
  • Polyline クラス
    一連の直線を描画
  • Path クラス
    一連の直線と曲線を描画

実装

  • ただし、Visual StudioではPath 要素の編集が困難である。
    このためExpression Blendのデザイナでは、[ペン]や[鉛筆]など、Path 要素の編集用ツールを使用すると良い。
    以下は、Expression Blendデザイナの[ペン]や[鉛筆]を使用して記述したPath 要素の描画である。
  • 画面
    様々なシェイプ(Path)
  • XAML
    <Grid>
      <Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="5"
        Data="M208,68 C182.37169,68 155.97712,69 131,69 ・・・"/>
      <Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="5" Margin="50"
        Data="M88,132 C88,132 87.5,250.5 120.5,234.5 ・・・"/>
    </Grid>
  • さらに、VSやExpression Blendを用い、Ellipse・TextBlock?などの描画コンテンツを作成し、
    これをExpression Blendで、これらをPath に変換するといった機能も用意されている。
  • 画面
    様々なシェイプ(Ellipse・TextBlock)
  • XAML
    <Grid>
      <Viewbox Height="400" Width="400">
        <Grid>
          <Ellipse Stroke="Black" StrokeThickness="5"
            Height="400" Width="400"/>
          <TextBlock Text="WPF" FontSize="150"
            HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
      </Viewbox>
    </Grid>
  • この変換を行うには、Expression Blend の[オブジェクトとタイムライン]でEllipse・TextBlock?を選択した状態で、
    メニューの[オブジェクト] → [パス] → [複合パスの作成]を選択する。以下は、上記のEllipse・TextBlock?をPath に変換したXAMLである。
  • XAML
    <Grid>
      <Path Data="M397.5,200 C397.5,309.07624 309.07624,397.5 200,397.5 C90.923762,397.5 2.5,309.07624 2.5,200 C2.5,90.923762 90.923762,2.5 200,2.5 C309.07624,2.5 397.5,90.923762 397.5,200 z M59.0835,149.3165 L71.974126,149.3165 L87.794437,223.73042 L107.13037,149.3165 L120.021,149.3165 L139.35694,223.73042 L155.17725,149.3165 L168.06787,149.3165 L145.80225,250.6835 L134.0835,250.6835 L113.57569,169.23834 L93.067874,250.6835 L81.349124,250.6835 z M192.08984,160.44929 L192.08984,199.1211 L222.55859,199.1211 C228.02734,199.1211 232.32422,197.5586 235.44922,194.4336 C238.96484,190.91799 240.72266,186.23049 240.72266,180.37113 C240.72266,173.73052 239.16016,168.84771 236.03516,165.72272 C232.51953,162.2071 228.02734,160.44929 222.55859,160.44929 z M178.61329,149.3165 L225.48828,149.3165 C234.08203,149.31651 241.11328,152.05088 246.58203,157.51961 C252.05078,162.98835 254.78515,170.60552 254.78515,180.37113 C254.78515,190.13674 252.24609,197.5586 247.16797,202.63671 C242.08984,207.71483 234.86328,210.25389 225.48828,210.25389 L192.08984,210.25389 L192.08984,249.51163 L178.61329,249.51163 z M273.5337,149.3165 L340.9165,149.3165 L340.9165,160.44929 L287.01027,160.44929 L287.01027,193.26173 L329.19775,193.26173 L329.19775,204.39452 L287.01027,204.39452 L287.01027,249.51163 L273.5337,249.51163 z" Stretch="Fill" Stroke="Black" StrokeThickness="5"/>
    </Grid>

参考

グラデーション

WPF / Silverlightでは、様々なグラデーションをデザイン可能。

実装

  • 簡単なグラデーション
    以下の簡素なグラデーションであれば、XAMLで直接記述することも可能。
  • 画面
    簡単なグラデーション
  • XAML
    <Window.Background>
      <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="Black" Offset="0"/>
        <GradientStop Color="White" Offset="1"/>
      </LinearGradientBrush>
    </Window.Background>
  • 複雑なグラデーション
    しかし、以下の複雑なグラデーションであれば、
    Expression Blendのデザイナを使用した方が、容易にグラデーションをデザインできる。
  • 画面
    複雑なグラデーション
  • XAML
    <Window.Background>
      <RadialGradientBrush GradientOrigin="0.3,0.3">
        <GradientStop Color="Aqua" Offset="0.1"/>
        <GradientStop Color="Black" Offset="0.2"/>
        <GradientStop Color="Aqua" Offset="0.3"/>
        <GradientStop Color="Black" Offset="0.4"/>
        <GradientStop Color="Aqua" Offset="0.5"/>
        <GradientStop Color="Black" Offset="0.6"/>
        <GradientStop Color="Aqua" Offset="0.7"/>
        <GradientStop Color="Black" Offset="0.8"/>
        <GradientStop Color="Aqua" Offset="0.9"/>
      </RadialGradientBrush>
    </Window.Background>

トランスフォーム処理

  • WPFで2D平面での変換を行う「トランスフォーム処理」を使用して以下の効果を追加できる。
    • 「回転、拡大縮小、傾斜、平行移動」
    • 「アニメーションなど一時効果」
  • 「トランスフォーム処理」に使用できるクラスには、
    System.Windows.Media名前空間のTransform クラスから派生する、下記クラスがある。
    • MatrixTransform?
    • RotateTransform?
    • ScaleTransform?
    • SkewTransform?
    • TranslateTransform?
    • TransformGroup?
  • なお、TransformGroup?を使用すれば、
    複数のTransformクラスを組み合わせて適用することができる。
  • 以下、下記の図形に対する、上記2つの「トランスフォーム処理」の例。
  • 画面
    トランスフォーム前
  • XAML
    <Grid>
      <Border Height="100" Width="100" BorderBrush="Black" BorderThickness="1" >
        <Rectangle Height="100" Width="100" Fill="Blue"/>
      </Border>
    </Grid>

回転、拡大縮小、傾斜、平行移動

  • FrameworkElement?.LayoutTransform?プロパティに設定されたTransformクラスを使用し、
    レイアウト時に「トランスフォーム処理」を実行する。
    • このため、「トランスフォーム処理」後もUI要素がレイアウト時の描画領域内に収まる。
    • このような特徴から、この「トランスフォーム処理」は、
      表示を垂直から水平に切り替えたり、ズームしたりするなどの用途で利用可能である。
  • 以下は、LayoutTransform?プロパティにRotateTransform?クラスを指定してUI要素を回転させた例である。
  • 画面
    回転、拡大縮小、傾斜、平行移動
  • XAML
    <Grid>
      <Border Height="100" Width="100" BorderBrush="Black" BorderThickness="1" >
        <Rectangle Height="100" Width="100" Fill="Blue">
          <Rectangle.LayoutTransform>
            <RotateTransform CenterX="50" CenterY="50" Angle="45"/>
          </Rectangle.LayoutTransform>
        </Rectangle>
      </Border>
    </Grid>

アニメーションなど一時効果の追加

  • UIElement.RenderTransform?プロパティに設定されたTransformクラスを使用し、
    レイアウト後に「トランスフォーム処理」しレンダリングする。
    • このため、場合によってはUI要素がレイアウトの描画領域の外にでてしまう場合がある。
    • このような特徴から、この「トランスフォーム処理」は、
      「アニメーション」(後述)と組み合わせるなどしてUI要素に注目を集めるなどの用途で利用可能である。
  • 以下は、RenderTransform?プロパティにRotateTransform?クラスを指定してUI要素を回転させた例である。
  • 画面
    アニメーションなど一時効果の追加
  • XAML
    <Grid>
      <Border Height="100" Width="100" BorderBrush="Black" BorderThickness="1" >
        <Rectangle Height="100" Width="100" Fill="Blue">
          <Rectangle.RenderTransform>
            <RotateTransform CenterX="50" CenterY="50" Angle="45"/>
          </Rectangle.RenderTransform>
        </Rectangle>
      </Border>
    </Grid>

※ なお、こちらの「トランスフォーム処理」は「Silverlight」でもサポートされる。

参考

アニメーション

実装

説明

参考

MVVMデザイン パターン

概要

MVVM(Model - View - View Model)モデルとは、
前述の「データ バインディング」の仕組みを活用したデザイン パターンであり、
従来の3層デザイン パターンの「モデル オブジェクト」、「ビュー オブジェクト」に加えて、
「バインディング ソース」である「ビュー・モデル オブジェクト」を新設するデザイン パターンである。

メリット

このデザイン パターンのメリットは、
「モデル オブジェクト」、「ビュー オブジェクト」間の結合部を、
「データ バインディング」による「ビュー・モデル オブジェクト」に限定し、疎結合を実現できる点である。

ガイドライン

なお、MVVMデザイン パターンのためのガイドライン には、以下のものがある。

  1. XAMLで実装できるものは、コードビハインドに実装しない。
  2. 「ビュー・モデル オブジェクト」はDataContext?として「ビュー オブジェクト」に渡す。
  3. 「ビュー・モデル オブジェクト」と「モデル オブジェクト」は、
    「データ バインディング」により結合されるため、「ビュー オブジェクト」には、一切アクセスしない。
  4. 「ビュー・モデル オブジェクト」は、INotifyPropertyChanged?インターフェイスを実装するべき。
  5. 「ビュー・モデル オブジェクト」は、「モデル オブジェクト」をカプセル化することで、
    「ビュー オブジェクト」から、データ ストレージの複雑さを隠蔽する。

参考

バリデーション

  • WPFのバリデーション・フレームワークの使い方。
  • 以下をプロトタイプ開発したので参考にすることができる。

単項目のバリデーション

https://github.com/OpenTouryoProject/SampleProgram/tree/master/UISubsystem/WPF/Validation/InputField

一覧のバリデーション

https://github.com/OpenTouryoProject/SampleProgram/tree/master/UISubsystem/WPF/Validation/DataGrid

フォーカス制御

フォーカス制御については、いろいろ試しているが
問題が多いので使わない方向で考えた方が良さそう。


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


添付ファイル: fileAfterRenderTransform.png 50件 [詳細] fileAfterLayoutTransform.png 54件 [詳細] filePreTransform.png 56件 [詳細] fileMVVM.png 47件 [詳細] fileEasyGradation.png 53件 [詳細] fileComplexGradation.png 59件 [詳細] filePath.png 57件 [詳細] fileEllipseAndTextBlock.png 64件 [詳細] fileIME-Control.png 66件 [詳細] fileTooltip.png 50件 [詳細] fileMenu_Taskbar_Command.png 73件 [詳細] fileNavigationServiceGoForwardAndGoBack.png 127件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-03-12 (月) 23:33:39 (491d)