Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Step up WPF

Grabacr07
August 01, 2016

Step up WPF

Metro.cs #2 発表資料

Grabacr07

August 01, 2016
Tweet

More Decks by Grabacr07

Other Decks in Programming

Transcript

  1. Agenda 最近の WPF 事情つまみ食い ここ 2 ~ 3 年の WPF

    へのアップデート Windows 10 / UWP 時代の WPF の立ち位置とは WPF を適切に乗りこなす コントロールの選択とカスタム実装の境界線 ライブラリ化までを見据えた再利用性のある実装
  2. Self Introduction 亀谷学人 (かめやまなと) • 1987年生まれ • 仙台出身 / 東京在住

    Windows Study Meeting (まどすた) staff Microsoft MVP for Visual Studio and Development Technologies 長いよ。 • ソフトウェア エンジニア • クライアント設計 / C# / XAML Twitter: @Grabacr07 Facebook: manato.kameya Blog: http://grabacr.net/
  3. My Apps KanColleViewer 「艦これ」 プレイング ツール C# + WPF (.NET

    Framework 4.6.2) SylphyHorn 仮想デスクトップ ツール アクティブ ウィンドウごと移動
  4. State of WPF Windows 10, UWP 時代の今 Classic Desktop とかいわれる

    「従来のデスクトップ」 だったことも… Visual Studio “15” では オプション扱い? XAML というと UWP という風潮 [要出典]
  5. WPF vs UWP Feature WPF UWP Windows Desktop (Simple app)

    ◯ ◯ Windows Desktop (Task tray, IE Shell, Keyhook, …) ◯ ✕ Universal Platform API (Live Tile, Cortana, Notifications, …) ✕ ◯ Other Platforms (Mobile, Xbox, IoT, HoloLens, …) ✕ ◯ Application distribution (Windows Store) ✕ ◯
  6. WPF vs UWP Feature WPF UWP Windows Desktop (Simple app)

    ◯ ◯ Windows Desktop (Task tray, IE Shell, Keyhook, …) ◯ ✕ Universal Platform API (Live Tile, Cortana, Notifications, …) ✕ ◯ Other Platforms (Mobile, Xbox, IoT, HoloLens, …) ✕ ◯ Application distribution (Windows Store) ✕ ◯ Windows Desktop に絞るなら WPF のほうがいいよ! (弱気)
  7. API Overview .NET Framework 4.5 以降の WPF DPI 関連の改修が多め [独自研究]

    High DPI と Per-Monitor DPI への対応 WPF はもともと DPI-aware DPI を意識しなくてもシステムが良しなに デバイス非依存ピクセル (DIP) 単位 WPF: 96 dpi での 1 px を 1 dip Android: 160 dpi での 1 px を 1 dip Android の場合は密度非依存ピクセルですが… Primary: 10.6” Tablet (1920 x 1080) 144 dpi (150 %)
  8. DPI Scaling 150 % 環境における DPI スケーリング そもそも、Border が 2

    px になるのは如何なものか Windows の VisualStyle は DPI 150 % でも Border は 1 px 1 px ではなく 0.99 と指定する となり、150 % 環境下でも Border = 1 px を再現可能 http://mntone.hateblo.jp/entry/2015/06/29/090728 Round (0.99 px * 150 %) = Round (1.485) = 1 px
  9. Per-Monitor DPI モニターごとの DPI スケーリング Primary: 10.6” Tablet (1920 x

    1080) Secondary: 24” Display (1920 x 1200) 144 dpi (150 %) 96 dpi (100 %)
  10. Per-Monitor DPI モニターごとの DPI スケーリング Windows 8.1 で追加された機能 (約 3

    年前…) モニターをまたいだときにウィンドウの DPI 変更 アプリ側が非対応の場合、単純な拡縮処理されてしまう
  11. Per-Monitor DPI aware WPF での従来の対応方法 ウィンドウ プロシージャー書いて WM_DPICHANGED MSDN の解説だと

    C++ コードが出てくる… private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == (int)WindowsMessages.WM_DPICHANGED) { var dpiX = wParam.ToLoWord(); var dpiY = wParam.ToHiWord(); this.ChangeDpi(new Dpi(dpiX, dpiY)); handled = true; } return IntPtr.Zero; }
  12. Per-Monitor DPI aware .NET Framework 4.6.2 Preview DpiChanged イベントが追加された 

    Window, HwndSource, Image public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } protected override void OnDpiChanged(DpiScale oldDpi, DpiScale newDpi) { base.OnDpiChanged(oldDpi, newDpi); } } ScaleTransform を使って ウィンドウの中身を拡縮 したりするとよいとおもう
  13. Windows Bridge for Classic Desktop App Windows 10 Anniversary Update

    (Insider Preview Build 14316 or later) デスクトップ アプリを UWP にするやつ
  14. Windows Bridge Desktop App Converter Win32 / .NET app を

    UWP パッケージ化する あくまでパッケージ化するだけで、中身はそのまま .msi をサイレント モードで動作させ、展開されたファイルを .appx へ MSI AppX ※ //build/ 2016 資料から引用
  15. WPF is UWP WPF in AppX は何者か UWP アプリ =

    Universal Platform 上で動くアプリ (つまり、対応デバイスの種類や数は関係ない) WPF in AppX = Windows 10 Desktop に対応した UWP アプリ 参考: UWP という表現と Desktop App Converter について https://blogs.msdn.microsoft.com/shintak/2016/05/25/uwpanddesktopappconverter/
  16. Desktop App Converter Bridge to the UWP UWP アプリへの 5

    つのステップ 将来的に UWP アプリへ移行してほしい (って Microsoft が言ってる) Desktop App Converter は Step 2 までを実現するツール Convert Enhance Extend Migrate Expand
  17. WPF vs UWP (2016) Feature WPF UWP Windows Desktop (Simple

    app) ◯ ◯ Windows Desktop (Task tray, IE Shell, Keyhook, …) ◯ ✕ Universal Platform API (Live Tile, Cortana, Notifications, …) ◯ ◯ Other Platforms (Mobile, Xbox, IoT, HoloLens, …) ✕ ◯ Application distribution (Windows Store) ◯ ◯
  18. WPF vs UWP (2016) Feature WPF UWP Windows Desktop (Simple

    app) ◯ ◯ Windows Desktop (Task tray, IE Shell, Keyhook, …) ◯ ✕ Universal Platform API (Live Tile, Cortana, Notifications, …) ◯ ◯ Other Platforms (Mobile, Xbox, IoT, HoloLens, …) ✕ ◯ Application distribution (Windows Store) ◯ ◯ Windows Desktop に絞るなら WPF のほうがいいよ! (強気)
  19. Bridge to the UWP Step 2: Enhance Desktop app 内部から

    UWP の API を呼び出し ライブ タイルのサポート Actionable Notifications (トースト通知操作) Cortana 他いろいろ Universal App Package Universal Windows API Classic Windows App
  20. Bridge to the UWP Step 3: Extend UWP App Service

    や Background tasks 等の機能追加 UWP App と Desktop App の共存  エントリー ポイントは UWP App 側へ  両者は App Service で通信 フロントエンドを XAML / コアを Win32 とか File Picker UI Universal App Package Universal Windows App Classic Windows App
  21. WPF in Windows 10 デバイスの多様化への対応 特に High DPI・Per-Monitor DPI 周り

    他、タッチ キーボード動作改善とか WPF も UWP へ Windows 10 Desktop 向けの UWP ㌠ パッケージ化してストア配布しよう
  22. XAML Platform 要件に対する適切な選択 表現力や柔軟性が非常に高い UI フレームワーク ControlTemplate, DataTemplate, Style, Trigger,

    Theme, Resource, … 数ある選択肢からもっとも要件にマッチした選択が必要 マウス オーバーと クリック時に 全体の色を変える… 円と矢印、 押しやすいように Margin 広めで… クリックすると 前の画面へ… ビットマップ画像? それともベクター? これを どう作るか?
  23. Control Authoring 新しいコントロールを作成しないために WPF の豊富なカスタマイズ機能 リッチ コンテンツ ボタン (に限らず) 中身何でも置ける

    テンプレート リスト項目でも何でも 自由なデータ表示方法 スタイル・トリガー 再利用可能な外観や 動作カスタマイズ
  24. Original Control Case study: ツイート入力ボックス これらの機能を満たす既成コントロールは存在しない  新しいコントロールを作成する必要がある 必要な機能 •

    テキスト入力 (文字列入力) • 残り文字数カウント (連動するカウンター) • ツイート送信ボタン (Click 相当イベント)
  25. User Control UserControl 型から派生するコントロール 最もシンプルな方法 • TweetInputBox1.xaml <DockPanel Margin="4"> <DockPanel

    DockPanel.Dock="Right" Margin="4"> <Label x:Name="Counter" DockPanel.Dock="Top" Content="140" /> <Button Content="Tweet" Click="ClickTweetButton" /> </DockPanel> <TextBox Text="{Binding RelativeSource={RelativeSource AncestorType=local:TweetInputBox}, Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="4" /> </DockPanel>
  26. User Control UserControl 型から派生するコントロール 最もシンプルな方法 • TweetInputBox1.xaml.cs public static readonly

    DependencyProperty TextProperty = DependencyProperty.Register( nameof(Text), typeof(string), typeof(TweetInputBox), new PropertyMetadata(default(string), TextPropertyChangedCallback)); public string Text { get { return (string)this.GetValue(TextProperty); } set { this.SetValue(TextProperty, value); } } private void ClickTweetButton(object sender, RoutedEventArgs e) { MessageBox.Show(this.Text, "Tweet!"); } コード ビハインドに サックリ書ける
  27. Custom Control Control 型から派生するコントロール WPF 標準コントロール群と同じ実装方法 • TweetInputBox2.cs ロジック (コントロール機能の実装)

    必要な機能 • テキスト入力 (文字列入力) • 残り文字数カウント (連動するカウンター) • ツイート送信ボタン (Click 相当イベント)
  28. Custom Control Control 型から派生するコントロール WPF 標準コントロール群と同じ実装方法 • TweetInputBox2.cs • Themes/Generic.xaml

    両者は「名前付きパーツ」で連携する XAML は x:Name で名前付け、ロジックは GetTemplateChild() で取得 ロジック (コントロール機能の実装) 視覚構造と動作 (コントロール外観の実装) PART_Remaining PART_SendButton
  29. Control Contract 機能 (ロジック) と外観の分離 あくまで View 内で分離しただけ (MVVM とか関係ない)

    視覚構造と動作は ControlTemplate で定義するのが重要 文字数オーバーしたら 数字を赤くしたい… Label の Foreground を SolidColorBrush の Red に…
  30. Control Contract 機能 (ロジック) と外観の分離 あくまで View 内で分離しただけ (MVVM とか関係ない)

    視覚構造と動作は ControlTemplate で定義するのが重要 文字数オーバーしたら 数字を赤くしたい… Label の Foreground を SolidColorBrush の Red に… VisualStates • Valid • Invalid オーバーしたときどうなるか …は、ControlTemplate 側で 自由に実装させるべき 検証結果を VisualState で保持
  31. Control Authoring 表現力・柔軟性を最大限利用しましょう Rich Content, Style, Trigger, Template, … 外観ではなく機能に着目してコントロールを選択

    コントロール作成時は再利用要件に注目 なし: User Control で楽々ポトペタ開発 あり: Custom Control で機能と外観をうまく分離