Slide 1

Slide 1 text

Road to UI Library 2014/11/29 Room metro #28 Manato KAMEYA (@Grabacr07)

Slide 2

Slide 2 text

Subject • UI Library 作ってました − MetroRadiance (最近弄ってない…) − UserControl / CustomControl の使いどころ共有 デモ & ライブコーディング中心 • UI Library によって − コントロール / UI 資産の再利用性を高める − アプリのブランド化 あたりに興味を持って頂けると!

Slide 3

Slide 3 text

Agenda デスクトップ アプリがこの先 生きのこるには Introduction CustomControl UserControl Conclusion Road to UI Library

Slide 4

Slide 4 text

• 内容は個人に帰属します 所属する組織を代表するものではありません

Slide 5

Slide 5 text

Introduction

Slide 6

Slide 6 text

Self Introduction • Work − 株式会社グラニ − Unity + C# でゲーム開発、まれに WPF • Private activity − Web: http://grabacr.net/ − Twitter: @Grabacr07 (ぐらばく) − めとべや東京勉強会スタッフ − Microsoft MVP for Visual C# (2014/04 ~)

Slide 7

Slide 7 text

KanColleViewer • Windows Desktop app − .NET Framework 4.5 − Visual C# + WPF • 艦これ プレイングツール Internet Explorer Shell + FiddlerCore • 2013/12 公開 (約 11 ヶ月) − 1,650,000 downloads − Azure の料金がやゔぁい!

Slide 8

Slide 8 text

KanColleViewer • 常にエゴサーチ (twitter) − メンタル鍛えられます • ユーザーの反応 − 機能に対する反応・要望 − UI に対する反応・要望 • デベロッパーの反応 − 「この見た目どうやって作んの」 UI ライブラリ自作しました

Slide 9

Slide 9 text

UI Libraries • 最近のリッチなデスクトップ アプリ

Slide 10

Slide 10 text

MetroRadiance • WPF カスタム コントロール ライブラリ − カスタム コントロール&スタイル群 − 別アプリでも同じ外観を再現できる ライブラリ (アセンブリ) を参照し、App.xaml の ResourceDictionary でマージするだけ − 自分で作ってるアプリのブランド化 社内向けツールとかも

Slide 11

Slide 11 text

UI Libraries • 最近のリッチなデスクトップ アプリ JetBrains 社のインストーラー • 独自 Style のコントロール群 • 標準 Chrome なし • Dark っぽいテーマ • 進行状況不定バー (WinRT のアレ) • ウィンドウの枠が光る • ウィンドウの枠が光る

Slide 12

Slide 12 text

Elysium • お手軽モダン UI ライブラリ これ使うだけでそれっぽく見える − http://elysium.codeplex.com/ − Zune 風コントロール・スタイル群 再現度はあまり高くない… − Visual Studio 2010 or 2012 が必要

Slide 13

Slide 13 text

Elysium • お手軽モダン UI ライブラリ これ使うだけでそれっぽく見える − http://elysium.codeplex.com/ − Zune 風コントロール・スタイル群 再現度はあまり高くない… − インストーラーに弾かれる VS2010 or 2012 が必要って言われる − 独自のトースト通知システム Windows 7 でも通知できるが…

Slide 14

Slide 14 text

MahApps.Metro • お手軽モダン UI ライブラリ これ使うだけでそれっぽく見える − http://mahapps.com/MahApps.Metro/ − Windows ストアアプリ風 コントロール・スタイル群 − 割とおすすめ

Slide 15

Slide 15 text

のちょっとした話? Template

Slide 16

Slide 16 text

Visual Structure (default Controls) • 既存コントロールの構造を知るには − 既定のテンプレートを生成

Slide 17

Slide 17 text

Another Controls ここにあるコントロールがすべて… なわけはない

Slide 18

Slide 18 text

Another Controls 右クリック > アイテムの選択 …で、表示するコントロールを選べる

Slide 19

Slide 19 text

Another Controls System.Windows.Controls.Primitives 名前空間 RepeatButton, Popup, …

Slide 20

Slide 20 text

まずはオリジナルのコントロールの作成 User Control

Slide 21

Slide 21 text

Original Control • NumericUpDown − WPF にない鉄板コントロールということでひとつ − ボタンが押しにくく、 使い勝手悪くなりがち … を、今ここで実際に作ってみましょう (!) 要件 • ユーザーによるテキスト入力 • ボタン (値 +1) • ボタン (値 - 1)

Slide 22

Slide 22 text

Case 1: User Control

Slide 23

Slide 23 text

Case 1: User Control • csproj > 追加 > ユーザー コントロール • NumericUpDown.xaml

Slide 24

Slide 24 text

Case 1: User Control • csproj > 追加 > ユーザー コントロール • NumericUpDown.xaml

Slide 25

Slide 25 text

• csproj > 追加 > ユーザー コントロール • NumericUpDown.xaml.cs (UserControl からの派生) public int Value { get { return (int)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(NumericUpDown), new PropertyMetadata(0)); private void CountUp(object sender, RoutedEventArgs e) { this.Value++; } Case 1: User Control 依存関係プロパティ

Slide 26

Slide 26 text

Case 1: User Control • 完成! … と、思うじゃろ? − そのときしか使わない場合は、それで完成。 − 他のプロジェクトでも使い回したい場合は…? そして、他のプロジェクトでは外観を変更したい場合は…? 次のアプリでも使うよ ただしボタンをデカくしてくれ 大変申し訳ございません早急に 影響調査し対応致しますので今 暫くお待ち頂きますよう宜しk

Slide 27

Slide 27 text

Feature of User Control • UserControl 型からの派生 − アプリケーション構築と同じ方法で作れる ▫ Window / Page を作成するのと同じ要領で、ポトペタ開発 ▫ 既存のコンポーネントだけで構成されている − 複雑なカスタマイズをサポートしない Background や BorderBrush を外部から指定する、程度の簡単なカスタマイズはでちる しかし、DataTemplate や ControlTemplate による外部からのカスタマイズはできない

Slide 28

Slide 28 text

外観をカスタマイズできるコントロールの作成 Custom Control

Slide 29

Slide 29 text

Case 2: Custom Control

Slide 30

Slide 30 text

Case 2: Custom Control • csproj > 追加 > 新しい項目 > WPF > カスタム コントロール (Universal apps の場合は「テンプレート コントロール」) − NumericUpDown2.cs − Themes/Generic.xaml <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:NumericUpDown2}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> </Border> </ControlTemplate> </Setter.Value> </Setter> 操作ロジック (コントロールの機能の実装) 視覚的表現 (コントロールの外観の実装) NumericUpDown2 は どうやって外観の定義まで 辿り着くか?

Slide 31

Slide 31 text

Feature of Custom Control • Control 型からの派生 − ロジックと外観の完全な分離 ▫ コントロールの振る舞いを、ロジック (.cs) に ▫ コントロールの外観を、Style/Template (Generic.xaml) に − .NET Framework が提供するコントロールと同じ実装 − コントロールの外観をカスタマイズ可能 ControlTemplate により、あらゆる外観に設定可能

Slide 32

Slide 32 text

Parts and States Model • 視覚的な構造と動作は ControlTemplate で定義 − 外観を直接ロジックで書くのはダメゼッタイ − NumericUpDown の場合 負の値のときは 文字を赤くしたい… TextBox の Foreground を SolidColorBrush の Red に…

Slide 33

Slide 33 text

Parts and States Model • 視覚的な構造と動作は ControlTemplate で定義 − 外観を直接ロジックで書くのはダメゼッタイ − NumericUpDown の場合 負の値のときは 文字を赤くしたい… TextBox の Foreground を SolidColorBrush の Red に… ValueStates • Positive • Negative 正負を VisualState で保持 負の値でどうなるか、は ControlTemplate で自由に実装

Slide 34

Slide 34 text

Parts and States Model • ControlTemplate とロジックの接点 − コントロールの要件 (命題) を満たすうえで必要なパーツ − NumericUpDown の場合 ▫ Click イベントを購読するため、ロジックから参照しなければならない Value を増減させるための Button が必ず必要 名前付きパーツと OnApplyTemplate メソッド

Slide 35

Slide 35 text

Parts and States Model • 名前付きパーツ − 例えば、System.Windows.Controls.ComboBox の場合 http://msdn.microsoft.com/ja-jp/library/ms752094.aspx

Slide 36

Slide 36 text

Parts and States Model • 名前付きパーツ − 例えば、System.Windows.Controls.ComboBox の場合 http://msdn.microsoft.com/ja-jp/library/ms752094.aspx ComboBox の ControlTemplate (default)

Slide 37

Slide 37 text

Parts and States Model • OnApplyTemplate メソッド − ControlTemplate の Visual Tree が構築されたとき実行される ロジックから ControlTemplate の実装にアクセスできる最も早いタイミング • GetTemplateChild メソッド − ControlTemplate 内の名前付き要素を返す ControlTemplate 内にある名前付きパーツのインスタンスを取得できる!

Slide 38

Slide 38 text

Parts and States Model • コントロール コントラクト − ロジックが使用する視覚的要素 名前付きパーツ − 視覚的に作用する public Property NumericUpDown でいう Value プロパティなど − コントロールの状態とグループ VisualStates / VisualStatesGroup

Slide 39

Slide 39 text

Parts and States Model • コントロール コントラクト − ロジックが使用する視覚的要素 名前付きパーツ − 視覚的に作用する public Property NumericUpDown でいう Value プロパティなど − コントロールの状態とグループ VisualStates / VisualStatesGroup [TemplatePart(Name = "PART_UpButton", Type = typeof(Button))] [TemplatePart(Name = "PART_DownButton", Type = typeof(Button))] public class CustomControl1 : Control { private Button upButton; private Button downButton; public override void OnApplyTemplate() { base.OnApplyTemplate(); this.upButton = this.GetTemplateChild("PART_UpButton") as Button; if (this.upButton != null) { this.upButton.Click += (sender, e) => this.Value++; } // 以下略

Slide 40

Slide 40 text

Custom Control • リソースを検索する順序 1. 要素レベル 参照する要素からルート要素まで辿って検索 2. アプリケーション レベル Application (App.xaml) 内で定義されたリソース 3. テーマ レベル Themes フォルダー内。つまり Generic.xaml Luna.NormalColor.xaml とか使わんし…

Slide 41

Slide 41 text

Custom Control • リソースを検索する順序 1. 要素レベル 参照する要素からルート要素まで辿って検索 2. アプリケーション レベル Application (App.xaml) 内で定義されたリソース 3. テーマ レベル Themes フォルダー内。つまり Generic.xaml Luna.NormalColor.xaml とか使わんし… NumericUpDown.Resources、 Border.Resources、StackPanel.Resources、 Grid.Resources、… の順に検索

Slide 42

Slide 42 text

Custom Control • リソースを検索する順序 1. 要素レベル 参照する要素からルート要素まで辿って検索 2. アプリケーション レベル Application (App.xaml) 内で定義されたリソース 3. テーマ レベル Themes フォルダー内。つまり Generic.xaml Luna.NormalColor.xaml とか使わんし… ※ ただしアプリケーションのみ ライブラリ (.dll) は Application を 持たないので

Slide 43

Slide 43 text

Custom Control • リソースを検索する順序 1. 要素レベル 参照する要素からルート要素まで辿って検索 2. アプリケーション レベル Application (App.xaml) 内で定義されたリソース 3. テーマ レベル Themes フォルダー内。つまり Generic.xaml Luna.NormalColor.xaml とか使わんし…

Slide 44

Slide 44 text

DependentUpon - Generic.xaml • Generic.xaml、だいたい溢れる カスタム コントロールが増えてくると、保守たいへん − なので、Generic..xaml に分離して DependentUpon すると良さげ .csproj 手動編集はつらすぎるので、拡張機能「VSCommands」とかとか

Slide 45

Slide 45 text

Without creating a new control • 新しいコントロールを自作しないための方法 作らないで済むならそれに越したことはなく。 CircleButton、とか作りたくなってくるが… マウス オーバーと クリック時に 全体の色を変える… 円と矢印、 押しやすいように Margin 広めで… Dark テーマに 対応…

Slide 46

Slide 46 text

Without creating a new control • 新しいコントロールを自作しないための方法 作らないで済むならそれに越したことはなく。 CircleButton、とか作りたくなってくるが… マウス オーバーと クリック時に 全体の色を変える… 円と矢印、 押しやすいように Margin 広めで… Button + リッチ コンテンツ + Style で実現可能 カスタム コントロールを作る必要は、ない Dark テーマに 対応…

Slide 47

Slide 47 text

Find the best possible choice • コントロールの価値命題 − こそが重要 − 外観ではなく、コントロールの原理 / 振る舞い XAML Platform では、外観はいくらでも作り込めるので、一切関係ない TabControl ListBox ItemsControl 見た目は同じでも、要件が異なるので、それぞれ違うコントロールをベースにしている

Slide 48

Slide 48 text

Road to UI Library • 作ったコントロールの再利用性を高めるために − UserControl はワンオフの実装、その時だけに使える − CustomControl は、WPF などと同じコントロールの実装 − 再利用性を見込んで、の実装となると 断然カスタム コントロール (テンプレート コントロール)

Slide 49

Slide 49 text

Conclusion

Slide 50

Slide 50 text

Advent Calendar • XAML Advent Calendar 2014 http://qiita.com/advent-calendar/2014/xaml • ご参加頂きたく。