WPFのUIをFigmaでデザインする

# WPFのUIをFigmaでデザインする

## はじめに
本記事は、WPFで実装するUIのUIデザインをFigmaで作成する際のUIデザインの構築方法や各UI部品の作成方法をまとめたものである。  
筆者自身の考え方が多分に含まれるため、「間違ってるよ！」「もっといいやり方があるよ！」ということがあればそっと教えていただけると幸いです。  

## 目次

- [1. Figmaの用語解説](#1-figmaの用語解説)
  - [1.1. Frame](#11-frame)
  - [1.2. オートレイアウト](#12-オートレイアウト)
  - [1.3. コンポーネント](#13-コンポーネント)
- [2. 各パーツは実際のUIと同じ見た目・サイズにすること](#2-各パーツは実際のuiと同じ見た目サイズにすること)
- [3. UIデザイン作成の流れ](#3-uiデザイン作成の流れ)
  - [3.1. Frameを組み合わせてUI全体の構造を作成する](#31-frameを組み合わせてui全体の構造を作成する)
  - [3.2. 各UI要素を作成、配置する](#32-各ui要素を作成配置する)
    - [3.2.1. 簡単なベンチマークの方法(参考元のUIがある場合)](#321-簡単なベンチマークの方法参考元のuiがある場合)
    - [3.2.2. テキストボックス](#322-テキストボックス)
    - [3.2.3. ボタン](#323-ボタン)
    - [3.2.4. ラベル](#324-ラベル)
    - [3.2.5. ラジオボタン](#325-ラジオボタン)
    - [3.2.6. チェックボックス](#326-チェックボックス)


## 1. Figmaの用語解説

以降の内容を理解するうえで必要なFigmaの機能を紹介する。

### 1.1. Frame

Figmaにおいて、子要素をまとめるコンテナ的な役割を持つ機能である。  
子要素をまとめる機能としては"Group"も存在するが、後述の"オートレイアウト"はFrameでしか設定できない。  

### 1.2. オートレイアウト

指定したFrame内の子要素を縦や横方向に規則的に並べる機能。  
並べる方向のほか、子要素同士の余白(マージン)、上下左右のパディングも設定できる。  
また、オートレイアウトを設定したFrameは、子要素のサイズやFrameの親要素のサイズに合わせて自動伸縮させることができる。  

自動伸縮の種類は以下。
- 内包  
Frameの持つ子要素のサイズにFrameのサイズを合わせる。WPFのGrid.Definitionの"Auto"と同様の挙動。
- 拡大  
Frameの親要素のサイズにFrameのサイズを合わせる。WPFのGrid.Definitionの"*"と同様の挙動。

### 1.3. コンポーネント

デザインの中で複数回利用する要素を共通化する機能。  
複数回利用する要素をコンポーネント化しておくことで、何か変更がある場合にも親のコンポーネント一つを変更すれば、複製した要素(Figma上ではインスタンスと呼ばれる)のすべてに変更を反映することができる。  

## 2. 各パーツは実際のUIと同じ見た目・サイズにすること

UIデザインでFigmaを利用する理由として、「実装するUIと同じ見た目にすることで、実装前に見た目のUXを評価できる」ことが挙げられる。  
例えばボタンの位置や大きさ、ラベルの文章の内容などを、実物とほぼ同じUIデザインとして作成することで、UI全体のバランスや分かりやすさ(認知負荷の高低)をUIを実装する前に確認できる。  
さらに、プロトタイプを併用すれば実際のUIと同じインタラクションもUIデザイン上で実現できるため、ボタン押下時や画面遷移時のUXもUIを実装せずに評価できる。  

また、UIデザインには実装者のためのUIの設計図としての意味合いもある。  
そのため、UIのサイズやマージン・パディングの数値は、参考元のUIがある場合はかならずベンチマークして同じにする必要がある。  
これにより、実装者がFigmaの数値を確認することでUIデザイン通りのUIを実装できる。 

## 3. UIデザイン作成の流れ

以下の順番でUIデザインを構築する。
1. Frameを組み合わせてUI全体の構造を作成する
2. 各UI要素を作成、配置する  

各UI要素を作成してからボトムアップ的に組み立てるよりは、「どこにどんな要素を置くか」を全体的に考えながらFrameを組み合わせていく方が、WPFでのUI実装時の

### 3.1. Frameを組み合わせてUI全体の構造を作成する
 
FigmaのUIデザインはFrameの組み合わせで作成していく。  
その際、UIの意味的なまとまりを考えながらFrameを構築していくと、UIデザインの最終的な構造は、実際に実装するWPFのUIの構造とかなり近いものになる。

例えば以下のようなWPFのUIのUIデザインをFigmaで作成するとする。  
![sample_WPF_UI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/aa9e2d6d-42c5-5bbf-1dc7-dcc77f1b1162.png)

xamlは以下。
```xaml
<Grid Margin="5,10">

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

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

        <TextBlock Grid.Row="0" Text="一覧:" Margin="0,0,5,5"/>
        <ListView Grid.Row="1" Margin="0,0,5,5">
            <ListBoxItem Content="山田 太郎" />
            <ListBoxItem Content="山田 花子"/>
        </ListView>

    </Grid>

    <Grid Grid.Column="1">

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

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        
        <Label Grid.Row="0" Grid.Column="0" Margin="0,0,5,5" Content="名前:"/>
        <TextBox Grid.Row="0" Grid.Column="1" Margin="0,0,5,5" VerticalContentAlignment="Center"/>
        <Label Grid.Row="1" Grid.Column="0" Margin="0,0,5,5" Content="性別:"/>
        <StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center" >
            <RadioButton Content="男性" Margin="0,0,5,0"/>
            <RadioButton Content="女性" Margin="0,0,5,0"/>
        </StackPanel>
        <Label Grid.Row="2" Grid.Column="0" Margin="0,0,5,5" Content="メールアドレス:"/>
        <TextBox Grid.Row="2" Grid.Column="1" Margin="0,0,5,5" VerticalContentAlignment="Center"/>
        <Label Grid.Row="3" Grid.Column="0" Margin="0,0,5,5" Content="住所:"/>
        <TextBox Grid.Row="3" Grid.Column="1" Margin="0,0,5,5" TextWrapping="Wrap"/>
        <StackPanel Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Margin="5,5,5,5">
            <CheckBox IsThreeState="True" Content="DBに保存する"/>
            <CheckBox IsThreeState="True" Content="保存時に暗号化する"/>
            <CheckBox IsThreeState="True" Content="エクスポート可能にする"/>
        </StackPanel>
        <StackPanel Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2">
            <Button Content="保存" Height="23" Width="80" Margin="0,0,5,5" HorizontalAlignment="Right"/>
        </StackPanel>
    </Grid>
</Grid>
```
  
この場合、FigmaのUIデザインのFrameの構造としては以下のようになる。
![sample_Figma_UI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/0423ebe1-7796-e8d0-3140-c50167020202.png)

Frameごとに色分けをした状態が以下。  
![structure_Figma_UI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/78c7fe2e-2e14-be0c-6fa0-aef70b6dff0a.png)

そして、xamlのGridの構造とFrameを対応付けると以下のようになる。  
![structure_Grid_Code.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/8d583722-e72e-9736-c655-0bc67638286a.png)

UIデザインから実際にどのようにUIを実装するかは実装者にゆだねられるが、UIデザインの作成者にWPFの知識がある場合は、自分がUIを実装するときにGridの構造をどうするかを考えながらUIデザインを構築すると作成しやすいと思われる。

### 3.2. 各UI要素を作成、配置する

FigmaでUIデザインを作成する場合、ボタンやテキストボックスなどのコンポーネントは自作する必要がある。  
基本的な作成方法を以下に示す。

#### 3.2.1. 簡単なベンチマークの方法(参考元のUIがある場合)
参考元のUIのスクリーンショットを用意し、以下を確認する。
- 縦横のサイズ
- フォントサイズ
- 上下左右のマージン
- 枠線の太さ
- 角の丸み

Figma上にスクリーンショットを貼り付け、Rectangleをその上に配置して測りたいもののサイズにRectangleのサイズを合わせることで簡単にサイズの確認が可能。  
以下は文字の高さを確認する場合の例。  
![check_FontSize.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/c424173e-edd0-0061-7ab9-da2f9e714ba4.png)

スクリーンショット上のサイズを測りたい要素の幅や高さにRectangleのサイズを合わせて、表示される数値を確認すればよい。  

#### 3.2.2. テキストボックス

Frameの構造は以下。  
![structure_TextBox.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/790ac366-0a7a-8ee3-bae2-1943abaa1a27.png)

また、オートレイアウトや塗り・枠線の設定は以下。  
![setting_TextBox.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/1ba7932b-cd44-ac00-9316-9c94a242127b.png)

複数回利用する場合はコンポーネント化する。
その際、テキストボックスの表示文字列をプロパティ化しておくと、コンポーネント化しても内容を変更できる。  
方法は以下。
1. 作成したテキストボックスをコンポーネント化する
![createComponent_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/aeffb316-ea23-695f-6fd8-0dbb33720b37.png)

2. コンポーネント化したボタンのテキストを選択し、画像内赤枠のマークを押す 
![createComponent_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/ebbce32f-5843-d84a-007d-37b297a965b9.png)

3. プロパティ名と初期入力の文字列を設定する    
![createComponent_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/6a90d505-bb66-46bf-d587-f2968bd59f5e.png)

上記の設定をすることで、コンポーネントのインスタンスに以下のようなプロパティが追加され、表示文字列を変更可能になる。
![createComponent_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/6d9dde19-b092-d7c8-2dc1-b159b49ffa78.png)
![createComponent_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/dbae02f0-f70c-4b0b-6a8b-2b47ed6f85f8.png)

また、以下の項目でテキストの折り返しを設定できるため、そのテキストボックスで折り返しできることを示したい場合は、設定したうえでサンプルの文字列を表示して実装者側にわかるようにすること。  
![setting_Text_Wrapping.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/ff34efb6-b59b-3b7c-a53e-0344729f566b.png)
 ![](images/setting_Text_Wrapping.png)

#### 3.2.3. ボタン

Frameの構造は以下。
テキストボックス同様、複数回利用する場合はコンポーネント化する。  
![structure_Button.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/c2ecf4ef-afc6-0eb7-ba58-98f34b4cfd1d.png)

#### 3.2.4. ラベル

TextをFrameで囲んでオートレイアウトを設定して作成する。  
![label.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/6da56ce4-520d-cffc-a131-7a5f4876179e.png)

Figmaは、WPFのGridにあたるレイアウトは存在せず、単一方向のオートレイアウトを組み合わせて作成する必要がある。  
一般的にWPFのLabelは、Grid.ColumnDefinitionのWidthを"Auto"に設定することで最も長いラベルに合わせて横幅が設定されるようにできるが、Figmaではそれが不可能である。  
そのため、 Figma上では以下の方法でLabelの横幅を設定する。  
1. 最も長いラベル(今回の例であれば[メールアドレス:]ラベル)のFrameの横幅を[内包]に設定する。これにより、[メールアドレス:]ラベルに必要な横幅がわかる(今回の例では74px)。  
![howto_Create_Label_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/bbec717a-6633-acae-fb14-02315430717c.png)

2. その他の短いラベル(今回の例であれば[名前:]や[性別:]ラベル)のFrameの横幅を[固定]に設定し、[メールアドレス:]ラベルの横幅(74px)に揃える。  
![howto_Create_Label_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/6f8c85d8-d806-3309-88a2-19d4d663fd70.png)

#### 3.2.5. ラジオボタン

選択状態・未選択状態の2状態の見た目が必要になる。  
![radioButton.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/f111ed4c-7246-4b5e-1c6f-56e17230ad36.png)

構造は以下のように、ボタン部分とラベル部分をFrameで囲んで作成する。ボタン部分はEclipseで作成できる。  
![structure_RadioButton.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/f34c45c4-bc2a-f9a7-61f4-2178883b2544.png)

また、ボタン部分をコンポーネント化しておくとON・OFFの見た目の差し替えが簡単になる。  
![component_RadioButton.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/879086ae-d187-78a1-3180-5517848f6840.png)

Figmaの機能で、コンポーネントは"/"区切りで名前を付けることで階層化が可能である。  
差し替えの候補はデフォルトで同階層のコンポーネントになるため、今回の例であれば[Radiobutton]でグルーピングした[ON],[OFF]のコンポーネントが差し替えの候補として表示される。
![swap_Instance.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/6eec53bf-0069-4304-e130-c28368be4829.png)

**なぜ差し替え可能にしておくと良いか**

ボタン部分のコンポーネントは複数必要になるが、ラジオボタン自体のコンポーネントが一つで済み、変更に強くなるため。
例えばボタン部分とラベル部分の間のマージンを変えることになった場合に、選択状態と未選択状態の2つのラジオボタンのコンポーネントを作成していると、両方のマージンを変更しなければならなくなる。

#### 3.2.6. チェックボックス

選択状態・未選択状態の2状態の見た目に加え、未確定状態(子要素のチェックボックスでチェック・未チェックが混在している場合の親のチェック状態)の見た目が必要になる場合がある。  
 ![checkBox.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/4e75adf2-dd21-a60c-d8b1-1ca19c3ca483.png)
 
チェックマークはアイコン素材か画像を利用して作成する。  
ラジオボタン同様、チェック部分は別でコンポーネント化しておくと差し替えが楽になる。  

**画像を利用する場合**

画像は32×32や64×64などの正方形にしておくと加工が楽になる。  
難しい場合はFrameを利用する。    
画像と、正方形のFrameを用意する。  
![howto_CreateCheckBox_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/197af375-c05f-665f-b798-ec02acc0be26.png)

Frameの入れ子として画像を追加し(注意：Frameの塗りとして画像を追加しないこと。サイズ調整が不可能になるため。) 、ラジオボタンの中央がFrameの中央に来るようにx,yの数値を調整する。  
![howto_CreateCheckBox_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/a5f8da75-0259-19db-d964-63bf0430b80d.png)

またこのとき、Frameの[コンテンツを隠す]をONにする。  
これにより、画像のFrameからはみ出している部分がクリッピングされて非表示になる。    
![howto_CreateCheckBox_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/79722285-1113-9761-323c-4ee110301347.png) 
 
## さいごに
FigmaはWebデザイン向けのUIデザインツールではあるものの、デスクトップアプリ開発でも十分に威力を発揮するツールだと思います。  
特にオートレイアウトは便利なのでしっかり活用していきたいですね。