2013年01月18日

このブログについて

このブログはC# & WPFでの開発を始めて半年ほどの筆者が
記事を書く事により知識を深める為、
又、これからWPFを始めようという方の入門書を作成する為のブログです。

C#言語に関する内容などは必要最低限しか記載しない為
ある程度の知識がある方を対象としています。

筆者個人的にはWPFは簡単に短時間で時間もお金もかかってそうに見えるソフトが作れる為
何か新しい技術を身につけたいという方にもいいと思います。
C#にしてもWPFにしてもあまり業務で携わっているという方は少ないようです。
ただ、需要は確実にあるので身につけておいて損はありません。

ちなみにこのブログで得られる知識があれば仕事で通用するというわけでもありませんし
業務で使用するとなればこのブログに書いていない内容で身につけなければならないことが山ほどあります。

とはいえとりあえず何か作ってみて感覚をつかむ程度の気楽な気持ちで見ていただければと思います。

筆者としてもこのブログが3ヶ月ぐらいは続く事を祈りつつ始めたいと思います。




まずはC#から理解したいという方におすすめ
初心者にもわかりやすく解説してあるので、これ一冊でC#の基本が理解できます

posted by cw at 23:30| Comment(0) | 日記 | このブログの読者になる | 更新情報をチェックする

まずは環境構築

何もない状態でこれから始めようという方向けという事で
まずは環境構築についてから始めます。

VisualC#、WPFToolkitが既にインストールされているという方は読み飛ばしてください。

・まずはVisualC# Expressをインストールします。
 このブログではVisualC# 2010 Expressを使用します。
 以下のサイトからインストーラをダウンロード、インストールしてください。
 途中、使用許諾、インストールディレクトリの設定があるだけで特に難しい事はありません。
 インストールは10分ぐらいで終わります。
 http://www.microsoft.com/ja-jp/dev/express/default.aspx

・サービスパック1をインストールします。
 以下のページからVS10sp1-KB983509.exeをダウンロード、インストールします。
 http://www.microsoft.com/ja-jp/download/details.aspx?id=23691
 こちらも、使用許諾、インストールディレクトリの設定などがあるだけです。

 インストールしたVisualC#2010Expressを起動した時に
 サービスパックがインストールされていない場合は
 インストールを促すメッセージが表示されます。

・WPFToolkitをインストールします。
 VisualStudioをインストールするとLabel、TextBox等の標準のコントロールは付属しています。
 WPFToolkitはこの標準コントロール以外の開発途中のコントロールをまとめたものです。
 以下のページからWPFToolkit.msiをダウンロード、インストールしてください。
 http://wpf.codeplex.com/releases/view/40535

・環境の設定をします。
 ここでは開発に使用するエディタの設定をします。
 この設定は筆者が使用しやすいと思っている設定なので
 この通りにしなければならないというものではありません。
 使用する個人の使いやすい設定にカスタマイズしてください。

 @まずはVisualC# 2010 Expressを起動します。
 A初期インストール時はメニュー項目が少ない状態(基本設定)になっています。
  これを上級者設定にします。
  [ツールメニュー]-[設定]-[上級者設定]の順に選択してください。
1.jpg

 B次にオプションを設定します。
  [ツールメニュー]-[オプション]の順に選択してください。
1.jpg

 C表示されたオプション画面右下の『すべての設定を表示』のチェックを入れてください。
1.jpg

 D初期設定ではインデント文字がスペースになっているのでタブ文字にします。
  オプション画面左側のツリーから[テキストエディタ]-[C#]の順に選択します。
  右側の画面の『タブの保持』を選択します。
1.jpg

以上で環境設定は終了です。
次から実際のプログラムを作成しながらWPFの勉強をしていきます。
posted by cw at 23:00| Comment(0) | 導入 | このブログの読者になる | 更新情報をチェックする

[C# WPF]HelloWorld

今回はHelloWorldを作ってみます。
とりあえず動かしてみる程度に見てください。

VisualC# IDEを起動して[ファイルメニュー]-[新しいプロジェクト]の順に選択します。
表示された新しいプロジェクト画面から『WPFアプリケーション』を選択します。
画面下の名前にプロジェクト名を設定します。
この例では『HelloWorld』に設定しました。
1.jpg

作成したプロジェクトにはMainWindow.xaml、MainWindow.xaml.csができています。
MainWindow.xamlを開いた状態でツールボックスからラベルをドラッグして配置します。
1.jpg

するとxamlコードエディタに以下のコードが追加されます。

<Label Content="Label" Height="28" ... />


このContent=の後をHelloWorldに書き換えます。

<Label Content="HelloWorld" Height="28" ... />


実行してみてください。
[デバッグメニュー]-[デバッグ開始]の順に選択するかF5キーを押下します。
以下のように表示されたらOKです。
1.jpg

現時点ではxamlコードに書いてある内容でわからない事がたくさんあると思いますが
順を追って解説していきますのでとりあえずは流しておいてください。
posted by cw at 22:30| Comment(0) | 導入 | このブログの読者になる | 更新情報をチェックする

[C# WPF]xamlについて

前回HelloWorldプログラムを作成してみました。

プログラムにはMainWindow.xaml、MainWindow.xaml.csの
2つのファイルが自動生成されていました。

WPFプロジェクトではGUIを持つクラスは
○○○.xamlと○○○.xaml.csの2つのファイルを作成します。

○○○.xamlにはGUIコントロールの配置やデータの表示方法について記述します。
○○○.xaml.csにはデータを処理するコードを記述します。

xamlに記述するのと同じ動作をする処理を
Windowsフォームプロジェクトのようにcsファイルに記述する事もできますが
同じ内容を書くならxamlのほうが圧倒的に記述量を減らす事ができます。
また、データの処理と表示を完全に分離する事で
仕様変更が発生しても柔軟に対応する事が可能になります。

xamlでは基本的には以下のように記述します。

<コントロール プロパティ=値/>

HelloWorldのMainWindow.xamlを見ていただくとわかりやすいと思います。

xamlの記述方法にはいくつかのパターンがありますので次回紹介します。



WPFでの開発はロジックと表示を分離できているかどうかで良し悪しが分かれます。
これからWPFを学ぶ上でこちらを手元においておくと非常に便利です。
筆者も普段使っているので安心してお勧めできる一冊です。

posted by cw at 22:00| Comment(0) | xaml | このブログの読者になる | 更新情報をチェックする

[C# WPF]xamlの記述方法

今回はxamlの記述方法について解説します。

前回の記事で書きましたが
基本的には以下のように記述します。

<コントロール プロパティ=値/>

Buttonを例に示すと以下のように記述します。

<Button Content="Button" Width="70" Height="23" Margin="5" Click="Button_Click"/>

また、以下のようにも記述できます。

<コントロール プロパティ=値>
</コントロール>

開始、終了タグの間にプロパティの設定や
子要素の定義をする場合にこのように記述します。

上のButtonの例では以下のように記述します。

<Button>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Content" Value="Button"/>
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="23"/>
<Setter Property="Margin" Value="5"/>
<EventSetter Event="Click" Handler="Button_Click"/>
</Style>
</Button.Style>
</Button>

このように記述する事に意味のない例ですが
このように記述する方法もあるという事だけ理解しておいてください。
Style、Setter等についても後の記事で解説しますので今は無視していただいてかまいませn。
posted by cw at 21:30| Comment(0) | TrackBack(0) | xaml | このブログの読者になる | 更新情報をチェックする

[C# WPF]レイアウト用のプロパティ

今回は多くのコントロールに共通するレイアウト用のプロパティについて解説します。

@Width、Height
AMargin
BHorizontalAlignment
CVerticalAlignment

ツールボックスからドラッグして配置すると上記のプロパティが自動的に設定されます。

@Width、Height
これはコントロールの幅、高さです。
double型の浮動小数点数値で指定しますが
Autoを指定すると表示内容などから自動的に割り当てられます。

AMargin
これはコントロールの周囲の余白です。
左右上下それぞれの4つの値を指定できますが、省略する事もできます。
値を4つ指定する場合は以下のように指定します。

Margin="左側の余白幅,上側の余白高さ,右側の余白幅,下側の余白高さ"

値を1つしか指定しない場合は上下左右全てに指定した値の余白が適用されます。
値を2つ指定した場合は1番目の値が左右の余白幅、2番目の値が上下の余白高さとなります。
値を3つだけ指定する事はできません。

BHorizontalAlignment
水平方向の配置方法を指定します。
以下の値を設定できます。
Leftコントロールを領域の左端を基準に配置します。
これを指定した場合Marginの右側の値を指定しても無視されます。
Rightコントロールを領域の右端を基準に配置します。
これを指定した場合Marginの左側の値を指定しても無視されます。
Centerコントロールを領域の中央に配置します。
これを指定した場合Marginの左右の値は無視されます。
Stretch配置されている領域の水平方向を埋めるように配置します。
Widthプロパティに値を設定しているとLeftを指定したのと同じ状態になります。
領域を埋めるように配置するためにはWidthプロパティにAutoを設定します。

CVerticalAlignment
垂直方向の配置方法を指定します。
以下の値を設定できます。
Topコントロールを領域の上端を基準に配置します。
これを指定した場合Marginの下側の値を指定しても無視されます。
Bottomコントロールを領域の下端を基準に配置します。
これを指定した場合Marginの上側の値を指定しても無視されます。
Centerコントロールを領域の中央に配置します。
これを指定した場合Marginの上下の値は無視されます。
Stretch配置されている領域の上下方向を埋めるように配置します。
Heightプロパティに値を設定しているとTopを指定したのと同じ状態になります。
領域を埋めるように配置するためにはHeightプロパティにAutoを設定します。

いろいろ値を変えてみながらどのように配置されるか確認してみましょう。
posted by cw at 20:30| Comment(0) | TrackBack(0) | レイアウト | このブログの読者になる | 更新情報をチェックする

[C# WPF]レイアウト用のコントロール

今回からレイアウト用のコントロールについて解説します。

C#のFormアプリケーションでは各コントロールが
自分の位置の基準、基準からのオフセット位置、サイズのプロパティを持っており
これらの値を指定してレイアウトをします。

WPFには各コントロールをレイアウトする為の専用のコントロールがあり、
レイアウトの記述がしやすくなっています。

次回以降で以下のレイアウト用のコントロールについてサンプルを交えながら解説します。
@Grid
AStackPanel
BWrapPanel
CDockPanel
DCanvas
posted by cw at 20:00| Comment(0) | レイアウト | このブログの読者になる | 更新情報をチェックする

[C# WPF]Grid

今回はレイアウト用のコントロールであるGridについて解説します。

Gridは縦横を格子状に区切って、
Grid上のコントロールにどこからどこまでの領域に配置するかを
指定してレイアウトするコントロールです。

扱いやすく非常に強力なレイアウトコントロールです。

Gridの定義はxamlに以下のような形式で記述します。

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=高さ指定/>
<RowDefinition/>



</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=幅指定/>
<ColumnDefinition/>



</Grid.ColumnDefinitions>
<Grid上に配置するコントロール Grid.Row=配置する行
                 Grid.Column=配置する列
                 Grid.RowSpan=コントロールの占める行数
                 Grid.ColumnSpan=コントロールの占める列数 />



</Grid>


Grid.RowDefinitionsの中に行の定義を記述します。
Grid.ColumnDefinitionsの中に列の定義を記述します。
それぞれ行、列の数だけ記述します。

RowDefinitionのHeightには行の高さを指定します。
数値を指定した場合は、その値の高さが割り当てられます。
数値と*(スター)を指定した場合は数値を比率として扱い、
対象領域を指定値の割合で分割した高さが割り当てられます。
数値を指定せず*だけの場合は1*と同義になります。
Autoを指定した場合は内部に配置するコントロールのサイズを元に自動的に割り当てられます。
Heightを指定しなかった場合は*になります。

ColumnDifinitionのWidthには列の幅を指定します。
指定方法はRowDefinitionのHeightと同じです。

Grid内に配置するコントロールには
Grid.Row、Grid.Column、Grid.RowSpan、Grid.ColumnSpanを設定できます。
それぞれ配置する行、列、コントロールの占める行数、列数です。
Row、ColumのマスからRowSpan、ColumnSpanの数の領域をコントロールに割り当てます。
指定しない場合はRow、Columnは0、RowSpan、ColumnSpanは1が設定されます。

サンプルを見てみましょう。

<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox Grid.Row="1" Grid.Column="2" Grid.RowSpan="2" Grid.ColumnSpan="3"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Blue"/>
<TextBox Grid.Row="3" Grid.Column="1" Grid.RowSpan="2"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Red"/>
</Grid>


レイアウトのされ方を見るためだけのものなので何の意味もないコードです。
わかりやすいようにTextBoxの背景を青、赤にして配置しています。

レイアウトのイメージを見てみましょう。
1.jpg

これはデザイナ画面で見たイメージです。
行、列の幅、高さを指定していない為、領域を同じ比率の幅、高さで分割します。
内部のTextBoxはRow、Column、RowSpan、ColumnSpanで指定した領域を占めています。

次のサンプルを見てみます。

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Row="1" Grid.Column="1" Background="Blue"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Grid>


水平方向を2:1:1、垂直方向を1:2:1の比率で3行3列に分割しています。

配置のイメージです。
1.jpg

複数の行や列の幅、高さに数値、Auto、*を混合して指定した場合は、
まず数値、Autoで指定した行、列の領域を割り当て、
残りの領域を*で指定した比率で分割して割り当てます。
posted by cw at 19:30| Comment(0) | レイアウト | このブログの読者になる | 更新情報をチェックする

[C# WPF]StackPanel

今日はレイアウトパネルの一つであるStackPanelを紹介します。

StackPanelは内部のコントロールを整列して配置するコントロールです。
積み上げるように配置するイメージからStackという名称になっています。


<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel>
<Button Content="Menu1" Width="70" Height="23" Margin="5"/>
<Button Content="Menu2" Width="70" Height="23" Margin="5"/>
<Button Content="Menu3" Width="70" Height="23" Margin="5"/>
<Button Content="Menu4" Width="70" Height="23" Margin="5"/>
<Button Content="Menu5" Width="70" Height="23" Margin="5"/>
</StackPanel>
<GridSplitter Grid.Column="1" Width="3" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
</Grid>


サンプルです。
StackPanelの中に5つのボタンを配置しています。
実行イメージは以下のようになります。
1.jpg

ボタンは画面左側の領域に整列して配置されます。
メニューボタンを作る場合などはこのようにしたらよいかと思います。

Orientationプロパティを設定する事で積み上げる方向を
水平、又は垂直方向に設定できます。
指定しない場合は垂直方向です。

Orientationを指定したサンプルです。

<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button Content="Button1" Height="23" Margin="5"/>
<Button Content="Button2" Height="23" Margin="5"/>
<Button Content="Button3" Height="23" Margin="5"/>
</StackPanel>
</Grid>


Orientation=Horizontalにして内部にボタンを3つ配置しています。

実行イメージです。
1.jpg

内部のコントロールは積み上げる方向において
決して重なる事はありません。

OK、Cancelボタンなどは画面右下に配置したい場合が多いと思います。
そういった場合にはOrientation=HorizontalのStackPanelの
HorizontalAlignmentをRightに設定する事で実現できます。


<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="OK" Height="23" Margin="5"/>
<Button Content="Cancel" Height="23" Margin="5"/>
</StackPanel>
</Grid>


実行イメージはこんな感じです。
1.jpg

StackPanelはそれを配置するコントロール(Window等)のサイズより
大きくなるとサイズを超えた部分は切れて表示されません。

以下のサンプルはStackPanelにボタンを7個配置したものですが
5個目のボタン以降のボタンは表示できていません。
1.jpg

こういった場合にできるだけ切れずに表示したい場合には
次に紹介するWrapPanelを使います。
posted by cw at 19:00| Comment(1) | レイアウト | このブログの読者になる | 更新情報をチェックする

[C# WPF]WrapPanel

前回紹介したStackPanelは内部のコントロールを整列して配置するコントロールでした。

今回紹介するWrapPanelもStackPanelと同じく整列して配置するPanelです。

ただし、StackPanelがそれを配置するコントロールより大きくなると
そのサイズを超える部分が切れて表示されないのに対して、
WrapPanelは折り返して表示できる部分は表示します。

StackPanelで一部が切れてしまった場合に、
切れた部分のコントロールを操作する場合には
スクロールしなければなりませんが
WrapPanelにすればより多くのコントロールを表示できるので
こちらの方がいいという場合もあると思います。

まずはStackPanelを使用したサンプルを見てみます。

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<GridSplitter Width="3" HorizontalAlignment="Right" VerticalAlignment="Stretch"/>
<StackPanel Grid.Column="1">
<Button Content="Item" Width="40" Height="40" Margin="5"/>
<Button Content="Item" Width="40" Height="40" Margin="5"/>
<Button Content="Item" Width="40" Height="40" Margin="5"/>
<Button Content="Item" Width="40" Height="40" Margin="5"/>
<Button Content="Item" Width="40" Height="40" Margin="5"/>
</StackPanel>
</Grid>


StackPanelにボタンを5つ配置しています。
これはツールボックスにツールアイテムのアイコンを表示するイメージです。

実行結果は次のようになります。
1.jpg
StackPanelの大きさよりもそれを配置しているWindowのサイズが小さくなると
表示しきれずに切れてしまいます。
上のイメージでは5つ目のButtonが切れています。
これはStackPanelの幅を変えても変わりません。
1.jpg

次に同じことをWrapPanelを使ってやってみます。

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<GridSplitter Width="3" HorizontalAlignment="Right" VerticalAlignment="Stretch"/>
<WrapPanel Grid.Column="1">
<Button Content="Item" Width="40" Height="40" Margin="5"/>
<Button Content="Item" Width="40" Height="40" Margin="5"/>
<Button Content="Item" Width="40" Height="40" Margin="5"/>
<Button Content="Item" Width="40" Height="40" Margin="5"/>
<Button Content="Item" Width="40" Height="40" Margin="5"/>
</WrapPanel>
</Grid>


StackPanelをWrapPanelに置きかえただけです。
実行結果は以下のようになります。
1.jpg

WrapPanelの幅が狭い場合にはStackPanelの時のように
Windowサイズを超える部分は切れてしまいます。
しかし、WrapPanelの場合は幅を広げると水平方向にも表示できるだけ表示してくれます。
1.jpg

一画面で操作を完結できるのは大きな違いです。

今回のサンプルで気づかれたかと思いますが
StackPanelもWrapPanelも表示が切れた場合でもスクロールバーなどは表示されません。
スクロールバーを表示したい場合はScrollViewerというコントロールを使う必要があります。
ScrollViewerを使ったサンプルは別の記事で紹介したいと思います。
posted by cw at 18:30| Comment(0) | レイアウト | このブログの読者になる | 更新情報をチェックする

[C# WPF]DockPanel

DockPanelは内部に配置するコントロール毎に
指定した方向、サイズの領域を埋めるように配置していきます。

xamlで記述した順番で配置していき、
常に残りの領域を対象に配置していきます。

内部のコントロール同士は重なる事はありません。

LastChildFillプロパティをTrueに設定すると
最後のコントロールで残りの全ての領域を埋めます。
LastChildFillプロパティをTrueに設定した場合、
最後のコントロールにレイアウト用プロパティを設定していても無視されます。

サンプルです。

<Grid>
<DockPanel LastChildFill="False">
<TextBlock Text="@" DockPanel.Dock="Left" Width="20" Background="Blue" Foreground="White"/>
<TextBlock Text="A" DockPanel.Dock="Top" Height="30" Background="Red"/>
<TextBlock Text="B" DockPanel.Dock="Right" Width="40" Background="Yellow"/>
<TextBlock Text="C" DockPanel.Dock="Bottom" Height="50" Background="Green"/>
</DockPanel>
</Grid>


DockPanelの動作を説明する為だけのサンプルですのでなんの意味もないものです。
DockPanelの内部に4つのTextBlockを配置しています。
わかりやすいように番号と色をつけています。

実行結果は以下のようになります。
1.jpg

DockのLeft、Top、Right、Bottomプロパティを設定して。
対象のコントロールで埋める方向を指定します。
コントロールのWidth、Heightプロパティでサイズを設定できますが、
DockのLeft又はRightを指定した場合はそれぞれ左側、右側の幅Widthの領域、
DockのTop又はBottomを指定した場合はそれぞれ上側、下側の高さHeightの領域の
全てが使用済みとなり、以降のコントロールはこの領域と重なる事はありません。


<Grid>
<DockPanel LastChildFill="False">
<TextBlock Text="@" DockPanel.Dock="Left" Width="20" Height="20" Background="Blue" Foreground="White"/>
<TextBlock Text="A" DockPanel.Dock="Top" Height="30" Background="Red"/>
<TextBlock Text="B" DockPanel.Dock="Right" Width="40" Background="Yellow"/>
<TextBlock Text="C" DockPanel.Dock="Bottom" Height="50" Background="Green"/>
</DockPanel>
</Grid>


先ほどのサンプルの左側に配置したTextBlockの高さを指定しました。
以下のような実行結果になります。

1.jpg

左側のTextBlockの高さは小さくなっていますが
画面の左側部分の領域は使用済みとなっています。
2つ目以降のTextBlockは画面左端の領域と重ならないように配置されます。

DockPanelは画面を領域毎に区切って配置するのに使用しますが、
筆者は同じような事をしたい場合にはいつもGridで対応しています。

今回DockPanelのLeft、Top、Right、Bottomプロパティを内部のコントロールに設定しました。
このようなプロパティは添付プロパティといいます。
改めて別の記事で紹介します。
posted by cw at 18:00| Comment(0) | レイアウト | このブログの読者になる | 更新情報をチェックする

[C# WPF]Canvas

前回までにレイアウト用のコントロールとしてGridと3つのPanelを紹介しました。
Gridは行列を区切って内部のコントロールを行、列を指定して配置します。
Panelは内部のコントロールをそれぞれのPanel毎の法則に沿って整列して配置します。

今回はCanvasを紹介します。
Canvasは内部のコントロールにCanvasの基準点からの距離(座標)を指定して配置します。

図形を描画する際などに使用します。

サンプルを見てみます。

<Grid>
<Canvas>
<Rectangle Width="60" Height="60" Stroke="Black" StrokeThickness="1"
Canvas.Left="20" Canvas.Top="20"/>
<Ellipse Width="100" Height="100" Fill="Blue"
Canvas.Left="100" Canvas.Top="40" Canvas.Right="10" Canvas.Bottom="10"/>
<Rectangle Width="100" Height="100" Fill="Red"
Canvas.Right="100" Canvas.Bottom="60" />
</Canvas>
</Grid>


Canvasの中に3つの図形を描きます。
各図形のプロパティではサイズや色、枠線の色や幅を設定しています。
見ていただきたいのは赤字で示したCanvas.Left、Top、Right、Bottomの部分です。
これらはキャンバスの基準点からの距離を指定する添付プロパティです。
(添付プロパティについては後の記事で解説します)
Left、Top、Right、Bottomはそれぞれ左端、上端、右端、下端からの距離になります。

LeftとRight、TopとBottomは両方指定する事もできますが、
RightよりLeft、BottomよりTopが優先されます。

実行結果です。
1.jpg

円の図形はLeft、Top、Right、Bottom全て指定していますが、
Left、Topに指定した位置に配置されています。
posted by cw at 17:30| Comment(0) | レイアウト | このブログの読者になる | 更新情報をチェックする

[C# WPF]Bindingを使ってみる

今回からBindingの基礎について解説していきます。
Bindingはビジネスロジックと表示処理を分離する為には非常に有効な機能です。
Bindingに慣れてしまうとC#のFormアプリケーションでの開発に戻れなくなります。
といっても過言ではないぐらいにすばらしい機能です。

では実際にサンプルを作成しながら見ていきます。

xamlコードです。

<Grid>
<TextBox Height="23" Width="70" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"
Text="{Binding Message}" />
<Button Content="Button" Height="23" Width="70" Margin="5,35,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top"
Click="Button_Click"/>
</Grid>

HelloWorldの時と同じようにTextBoxとButtonを配置します。

ButtonのClickプロパティはボタンクリック時のイベントハンドラを設定しています。
イベントハンドラはxaml.csに実装します。

そして、赤字で示したTextBoxのTextプロパティがBindingの記述です。
この記述はTextプロパティにMessageプロパティを割り当てるという意味になります。
MessageプロパティはMainWindowクラスのプロパティで.csファイルに定義しています。

csコードです。

public partial class MainWindow : Window
{
public string Message { get; set; }

public MainWindow()
{
InitializeComponent();

this.DataContext = this;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Message);
}
}


見て頂きたいのは赤字の部分です。
MessageプロパティはTextBoxのTextプロパティにBindするプロパティの定義です。
Bindingソースとするプロパティはpublicでなければなりません。

そして

this.DataContext = this;

これはMainWindow.xamlで使用するBindingソースを検索する基準を
自分自身(MainWindowクラスオブジェクト)にするという記述です。
上記のように指定するとxamlに以下のように記述した場合、
MessageプロパティはMainWindowクラスのメンバから検索されます。

{Binding Message}


xamlも合わせて以上のように記述する事で
TextBoxのTextプロパティにMainWindowクラスのMessageプロパティが割り当てられ、
TextBoxに入力した値がMessageプロパティに設定されるようになります。

それでは実行して動作を確認してみましょう。
1.jpg

TextBoxを編集するとTextプロパティの値(入力した文字列)が
BindingソースであるMessageプロパティに設定されます。
ボタンを押すと入力した文字列をダイアログ表示します。

このサンプルを見て気付かれたと思いますが
xaml.csコードにはデータに対する処理しか書かれておらず、
データの表示のしかた、編集のしかたはすべてxamlにのみ記述されています。
これが表示とビジネスロジックを分離するという事です。
posted by cw at 16:30| Comment(0) | Binding | このブログの読者になる | 更新情報をチェックする

[C# WPF]Binding DataContextを設定する

前回の記事で解説しましたが
DataContextにはBindingソースプロパティを検索する基準になるオブジェクトを指定するのでした。
このDataContextについてもう少し見ていきます。

サンプルは前回のものをそのまま使用します。
xamlコードは前回のままで結構です。

csコードを以下のように変更します。

public partial class MainWindow : Window
{
public string Message { get; set; }

public TestData Data { get; set; }

public MainWindow()
{
InitializeComponent();

Data = new TestData();

this.DataContext = Data;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("MainWindow.Massage=" + Message + "\nTestData.Message=" + Data.Message);
}
}

public class TestData
{
public string Message { get; set; }

public TestData()
{
}
}


Messageプロパティを持つTestDataクラスを定義して
MainWindowクラスのメンバにTestDataクラスオブジェクトを持ちます。
そしてMainWindowのDataContextにはこのTestDataオブジェクトを設定します。
こうすることによりTextBoxのTextプロパティにBindするMessageプロパティは
TestDataオブジェクトのメンバが使用されます。

では実行してみましょう
1.jpg

TextBoxに入力した値はTestDataオブジェクトのMessageプロパティに設定されます。
MainWindowオブジェクトのMessageプロパティはデフォルト値(空)のままです。

BindingソースがDataContextに指定したクラスから設定されるという事がわかって頂けたと思います。
posted by cw at 16:00| Comment(0) | Binding | このブログの読者になる | 更新情報をチェックする

[C# WPF]Bindingソースの階層指定

今回はBindingソースの階層指定についてです。

xamlにBindingソースを"."で区切って指定する事で
DataContextで指定したオブジェクト以下の階層を辿って指定する事ができます。

サンプルはまた前回のものを変更して使用します。

まずはxamlを以下のように変更します。

<Grid>
<TextBox Height="23" Width="70" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"
Text="{Binding Data.Message}" />
<Button Content="Button" Height="23" Width="70" Margin="5,35,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top"
Click="Button_Click"/>
</Grid>


Textプロパティの設定部分(赤字部分)を変更しています。
DataContextであるMainWindowオブジェクトのメンバから階層を辿って指定します。

次にcsコードを以下のように変更します。

public partial class MainWindow : Window
{
public string Message { get; set; }

public TestData Data { get; set; }

public MainWindow()
{
InitializeComponent();

Data = new TestData();

this.DataContext = this;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("MainWindow.Massage=" + Message + "\nTestData.Message=" + Data.Message);
}
}

public class TestData
{
public string Message { get; set; }

public TestData()
{
}
}


DataContextにはMainWindowクラスを指定しています。
xamlでMainWindowのメンバのTestDataオブジェクトの
Messageプロパティを辿って指定しているので
TextBoxに入力したデータはTestDataオブジェクトのMessageに設定されます。

実行結果は前回のサンプルと同じ結果になります。
posted by cw at 15:30| Comment(1) | Binding | このブログの読者になる | 更新情報をチェックする

[C# WPF]Bindingソースの更新を表示に反映する -NotifyPropertyChanged-

前回までは画面で編集したデータがBindingソースに設定される事を確認しました。
今回はBindingソースが更新されたら表示も更新されるようにします。

この為にINotifyPropertyChangedインターフェースを使用します。

サンプルを見ていきます。

xamlコードです。



<Grid>
<Label Height="23" Width="70" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"
Content="{Binding Data.Message}" />
<TextBox Height="23" Width="70" Margin="5,35,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top"
Text="{Binding Data.Message}" />
<Button Height="23" Width="70" Margin="5,70,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top"
Content="Button"/>
</Grid>




LabelとTextBoxとButtonを配置しています。
LabelのContentとTextBoxのTextにMessageプロパティをBindしています。
ButtonはTextBox以外のコントロールにフォーカスを移動する為だけに配置しています。

次にcsコードです。



public partial class MainWindow : Window, INotifyPropertyChanged
{
private string message;
public string Message
{
get { return message; }
set
{
message = value;
OnPropertyChanged("Message");
}
}

public MainWindow()
{
InitializeComponent();

this.DataContext = this;
}

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}

}




赤字の部分を見てください。
更新を表示に反映させたいBindingソースを持つクラスに
INotifyPropertyChangedインターフェースを実装します。
INotifyPropertyChangedはSystem.ComponentModel名前空間に属しているので
usingの指定もしてください。
INotifyPropertyChnagedインターフェースは
PropertyChangedEventHandlerイベントオブジェクトを持ちます。
表示に更新を反映したいプロパティの更新のタイミングで
PropertyChangedイベントを発行します。
イベント引数には変更されたプロパティ名を指定します。

では実行してみましょう。
1.jpg

TextBoxを編集してフォーカスをボタンに移動すると
LabelにTextBoxに入力した値が設定されます。

TextBoxを編集して値がBindingソースであるMessageプロパティに設定されると
PropertyChangedイベントを発行します。
このイベントが発行されるとMessageプロパティを
Bindingしているすべてのコントロールが更新されます。

TextBoxの編集した値がBindingソースに設定されるタイミングは
デフォルトではフォーカスが移動したタイミングです。
TextBoxからフォーカスを移動するためにButtonを配置しています。
posted by cw at 15:00| Comment(2) | Binding | このブログの読者になる | 更新情報をチェックする

[C# WPF]Bindingソースの更新タイミングを変える -UpdateSourceTrigger-

前回のサンプルでBindingソースの更新を 表示に反映するサンプルを見ました。
その際、Bindingソースが更新されるタイミングは
TextBoxからフォーカスが外れたタイミングでした。
Bindingソースを更新するタイミングを変えたい場面もあると思います。

Bindingソースの更新タイミングはBindingプロパティの
UpdateSourceTriggerで指定します。

サンプルを見てみましょう。
前回のサンプルのxamlを以下のように変更してください。

<Grid>
    <Label Height="23" Width="70" Margin="5"
           HorizontalAlignment="Left" VerticalAlignment="Top"
           Content="{Binding Message}" />
    <TextBox Height="23" Width="70" Margin="5,35,0,0"
             HorizontalAlignment="Left" VerticalAlignment="Top"
             Text="{Binding Message, UpdateSourceTrigger=PropertyChanged}" />
</Grid>

前回TextBoxからフォーカスを外す為にButtonを配置していましたが
今回は削除してLabelとTextBoxだけ配置しています。
そしてTextBoxのTextプロパティのBindingプロパティUpdateSourceTriggerに
PropertyChangedを指定しています。
これはプロパティ(TextBoxのText)値が更新されたらすぐに
Bindingソースに反映するという指定です。

では実行してみましょう。
1.jpg
TextBoxで文字列を編集すると即座にLabelの内容も更新されます。
TextBoxのTextプロパティが更新される度にBindingソースが更新されているという事です。

このBiningのUpdateSourceTriggerプロパティの
デフォルト値はコントロールによって違います。

UpdateSourceTriggerには以下のような設定があります。
Default 対象のコントロールのデフォルトの値です
Explicit ソースコード上からUpdateSourceメソッドを 呼び出したタイミングでBindingソースを更新します
LostFocus コントロールからフォーカスが離れたタイミングで Bindingソースを更新します
PropertyChanged Bindしたコントロールのプロパティ値が 更新されたタイミングでBindingソースも更新します
posted by cw at 14:30| Comment(0) | Binding | このブログの読者になる | 更新情報をチェックする

[C# WPF]他のコントロールのプロパティをBindする

今回は他のコントロールのプロパティをBindする方法を見ていきます。

サンプルを見てみましょう



<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Slider x:Name="slider" Width="300" Height="23" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
<TextBlock Grid.Column="1" Width="70" Height="23" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"
Text="{Binding Value, ElementName=slider}"/>
</Grid>



今回はxamlの記述のみです。
SliderとTextBlockを配置しています。

赤字部分を見てください。
Sliderの位置の値をTextBlockのTextプロパティにBindしています。
他のコントロールのプロパティをBindする場合は
Binding ElementNameに対象のコントロールの名前を設定します。

では実行して動作を確認してみましょう。
1.jpg

Sliderのバーを動かすとTextBlockに現在位置の値が表示されます。
posted by cw at 14:00| Comment(1) | Binding | このブログの読者になる | 更新情報をチェックする

[C# WPF]Binding Sourceプロパティを使う

今回はBinding Sourceプロパティを使ってみます。

Binding SourceプロパティはDataContextとは別の
オブジェクトのメンバをBindする場合に使用します。

サンプルを見てみます。

[xaml]

<Grid>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<TextBox Text="{Binding Text, Source={x:Static local:TestClass.Object}}" Width="70" Height="23" Margin="5"/>
<Button Content="Button" Height="23" Margin="5" Click="Button_Click"/>
</StackPanel>
</Grid>


[ソース]

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();

this.DataContext = this;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(TestClass.Object.Text);
}
}

public class TestClass
{
private static TestClass obj = new TestClass();
public static TestClass Object { get { return obj; } }

public string Text { get; set; }

private TestClass()
{
}
}


TestClassのシングルトンオブジェクトのプロパティをBindしています。
xamlのDataContextはMainWindowクラスオブジェクトなので
BindingのSourceにTestClassのオブジェクトを指定してBindしています。
このようにソースのstaticオブジェクトをBindする時は{x:Static オブジェクト}と記述します。

アプリ設定をシングルトンオブジェクトで管理している場合などに
そのオブジェクトのプロパティをBindする時に使います。

実行結果です。
1.jpg

TextBoxに入力してButtonを押すと入力した内容がMessageBoxに表示されます。
Staticに指定したオブジェクトのプロパティに設定されている事がわかります。
posted by cw at 13:30| Comment(1) | Binding | このブログの読者になる | 更新情報をチェックする

[C# WPF]Binding Converterプロパティを使う

今回はConverterを使用します。
ConverterはBindingソースと表示形式の間で変換が必要な時に使用します。

今回作成するサンプルではint型の数値を16進数文字列形式で表示します。

サンプルを見てみましょう。

xamlです。

<Window.Resources>
<local:HexConverter x:Key="HexConv"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}"
Width="70" Height="23" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
<TextBlock Text="{Binding Value, Converter={StaticResource HexConv}}"
Grid.Row="1" Width="70" Height="23" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>


赤字の部分を見てください。
csコードで実装しているHexConverterをリソース登録しています。
そしてTextBlockのTextプロパティのBindingでConverterを設定しています。
このサンプルはTextBoxに入力した値をTextBlockに16進数形式で表示します。

次にcsソースです。

public partial class MainWindow : Window, INotifyPropertyChanged
{
private int val;
public int Value
{
get { return val; }
set
{
val = value;
OnPropertyChanged("Value");
}
}

public MainWindow()
{
InitializeComponent();

this.DataContext = this;
}

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}

public class HexConverter : IValueConverter
{
public object Convert(object value, Type type, object parameter, CultureInfo culture)
{
int v = (int)value;
return string.Format("0x{0:X2}", v);
}

public object ConvertBack(object value, Type type, object parameter, CultureInfo culture)
{
string s = (string)value;
int v;
if (int.TryParse(s, NumberStyles.AllowHexSpecifier, null, out v))
{
return v;
}
return 0;
}
}



HexConverterを定義しています。
BindingConverterに指定するクラスはIValueConverterを実装します。
IValueConverterはConvertとConvertBackの2つのメソッドを持ちます。
ConvertがBindingソースからコントロールへのデータの受け渡し時に呼び出される変換
ConvertBackがその逆の際に呼び出される変換です。
サンプルのHexConverterはint型の数値データを16進数形式の文字列に変換します。

実行してみましょう。
1.jpg
TextBoxに値を入力するとTextBlockに16進数形式にして表示します。

このConverterの機構もビジネスロジックと表示処理を分離する為に欠かせない機能です。
BooleanToVisibilityConverter等標準で用意されているConverterもあります。
posted by cw at 12:30| Comment(0) | Binding | このブログの読者になる | 更新情報をチェックする

[C# WPF]Binding ConverterParameterプロパティを使う

今回はConverterParameterプロパティを使用してみます。
前回紹介したConverterにパラメータを渡す事ができます。
BindingのConverterParameterプロパティを設定します。

サンプルは前回のものに少し手を加えて使います。
では見てみましょう。

<Window.Resources>
<local:HexConverter x:Key="HexConv"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}"
Width="70" Height="23" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
<TextBlock Text="{Binding Value, Converter={StaticResource HexConv}, ConverterParameter=4}"
Grid.Row="1" Width="70" Height="23" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>


赤字部分でConverterParameterを指定しています。
今回のサンプルは16進数表記の桁数をパラメータで指定します。

Converterのソースです。

public class HexConverter : IValueConverter
{
public object Convert(object value, Type type, object parameter, CultureInfo culture)
{
int v = (int)value;
int p = int.Parse((string)parameter);
return string.Format("0x{0:X" + p.ToString() + "}", v);
}

public object ConvertBack(object value, Type type, object parameter, CultureInfo culture)
{
string s = (string)value;
int v;
if (int.TryParse(s, NumberStyles.AllowHexSpecifier, null, out v))
{
return v;
}
return 0;
}
}


xamlのConverterParameterで指定したパラメータは第三引数のparameterに入ります。
パラメータは文字列形式なのでParseしています。

実行してみます。
1.jpg

パラメータに4を設定しているので16進数表記4桁で表示されます。

ConverterParameterもBindingして動的に変更できればいいのですが
それができないのであまり使えません。
posted by cw at 12:00| Comment(0) | Binding | このブログの読者になる | 更新情報をチェックする

[C# WPF]BooleanToVisibilityConverterを使う

前回Converterについて解説しましたが、
BooleanToVisibilityConverter等の標準で用意されているConverterもあります。
BooleanToVisibilityConverterはbool値とVisibility値を変換します。
bool型のプロパティをコントロールのVisibilityプロパティにBindする時に使用します。

ではサンプルを見てみましょう。

<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<CheckBox Content="IsVisible" Width="70" Height="23" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"
IsChecked="{Binding IsTextBoxVisible, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Grid.Row="1" Width="70" Height="23" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top"
Visibility="{Binding IsTextBoxVisible, Converter={StaticResource BoolToVisibility}}"/>
</Grid>


TextBoxのVisibilityプロパティのBindingConverterにBooleanToVisibilityConverterを指定します。


public partial class MainWindow : Window, INotifyPropertyChanged
{
private bool isTextBoxVisible;
public bool IsTextBoxVisible
{
get { return isTextBoxVisible; }
set
{
isTextBoxVisible = value;
OnPropertyChanged("IsTextBoxVisible");
}
}

public MainWindow()
{
InitializeComponent();

this.DataContext = this;
}

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}


csコードのほうはBindingソースのboolプロパティを定義してあるのみです。

実行してみます。
1.jpg
1.jpg

チェックボックスONの時はTextBoxを表示して、
チェックボックスをOFFにするとTextBoxを非表示にします。

BooleanToVisibilityConverterはよく使うConverterです。
posted by cw at 11:30| Comment(0) | Binding | このブログの読者になる | 更新情報をチェックする

[C# WPF]MultiBinding MultiConverterを使う

今回はMultiBindingを使用してみます。
これまでのBindingは一つのターゲットプロパティに対して
一つのソースプロパティをBindしていました。
MultiBindingは一つのターゲットプロパティに対して
複数のソースプロパティをBindします。
また、複数項目を一つのプロパティ値に変換する
MultiConverterも使用します。

早速サンプルを見てみます。

<Window.Resources>
<local:NameConverter x:Key="NameConv"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Label Content="Last" Width="70" Height="23" Margin="5"/>
<TextBox Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}"
Width="70" Height="23" Margin="5"/>
<Label Content="First" Width="70" Height="23" Margin="5"/>
<TextBox Text="{Binding LastName, UpdateSourceTrigger=PropertyChanged}"
Width="70" Height="23" Margin="5"/>
</StackPanel>
<TextBlock Grid.Row="1" Width="150" Height="23" Margin="5"
HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text">
<Setter.Value>
<MultiBinding Converter="{StaticResource NameConv}">
<MultiBinding.Bindings>
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>


2つのTextBoxと1つのTextBlockを配置します。
TextBoxの値を苗字、名前として結合してTextBlockに表示します。
FirstName、LastNameの2つのプロパティをTextBlockのTextの1つのプロパティにBindします。


public partial class MainWindow : Window, INotifyPropertyChanged
{
private string firstName;
public string FirstName
{
get { return firstName; }
set
{
firstName = value;
OnPropertyChanged("FirstName");
}
}

private string lastName;
public string LastName
{
get { return lastName; }
set
{
lastName = value;
OnPropertyChanged("LastName");
}
}

public MainWindow()
{
InitializeComponent();

this.DataContext = this;
}

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}

public class NameConverter : IMultiValueConverter
{
public object Convert(object[] value, Type type, object parameter, CultureInfo culture)
{
string first = (string)value[0];
string last = (string)value[1];
return string.Format("{0} {1}", last, first);
}

public object[] ConvertBack(object value, Type[] type, object parameter, CultureInfo culture)
{
string name = (string)value;
string[] items = name.Split(' ');
return new string[] { items[1], items[0] };
}
}


csソースです。
MainWindowにはFirstName、LastNameプロパティを定義しています。
NameConverterも定義しています。
MultiBindingで使用するConverterクラスはIMultiValueConverterを実装します。
IValueConverterを同じでConvertとConvertBackメソッドを実装します。
IValueConverterとの違いは複数のプロパティを配列で扱います。

実行してみましょう。
1.jpg

2つのTextBoxに入力した苗字と名前を合わせてTextBlockに表示します。

Convertでは複数のプロパティから一つのプロパティに変換しますが、
ConvertBackを実装する場合Convertで変換した結果から元の複数の値を復元できる必要があります。

例えば複数の数値パラメータをConvertで加算した結果を返すようなConverterでは
ConvertBackで複数の数値パラメータを復元する事は不可能です。
posted by cw at 11:00| Comment(0) | Binding | このブログの読者になる | 更新情報をチェックする

[C# WPF]Styleを使う

今回からStyleについて解説していきます。

Styleは複数コントロールに共通するプロパティ設定をくくりだして
一箇所にまとめるのがもっとも基本的な使用方法です。

以下のサンプルを見てください。

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel>
<CheckBox Content="Enabled" x:Name="ButtonEnabled"/>
<Button Content="Button1" Width="70" Height="23" Margin="5"
IsEnabled="{Binding IsChecked, ElementName=ButtonEnabled}"/>
<Button Content="Button2" Width="70" Height="23" Margin="5"
IsEnabled="{Binding IsChecked, ElementName=ButtonEnabled}"/>
<Button Content="Button3" Width="70" Height="23" Margin="5"
IsEnabled="{Binding IsChecked, ElementName=ButtonEnabled}"/>
<Button Content="Button4" Width="70" Height="23" Margin="5"
IsEnabled="{Binding IsChecked, ElementName=ButtonEnabled}"/>
<Button Content="Button5" Width="70" Height="23" Margin="5"
IsEnabled="{Binding IsChecked, ElementName=ButtonEnabled}"/>
</StackPanel>
</Grid>


StackPanelの中にCheckBoxとButtonを5つ配置しています。
CheckBoxのON/OFFでButtonの有効状態を切り替えます。
5つのButtonを見るとWidth、Height、Margin、IsEnabledは同じ値です。

これをStyleを使って以下のように書く事ができます。

<Window.Resources>
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="23"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="IsEnabled" Value="{Binding IsChecked, ElementName=ButtonEnabled}"/>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel>
<CheckBox Content="Enabled" x:Name="ButtonEnabled"/>
<Button Content="Button1" Style="{StaticResource ButtonStyle}"/>
<Button Content="Button2" Style="{StaticResource ButtonStyle}"/>
<Button Content="Button3" Style="{StaticResource ButtonStyle}"/>
<Button Content="Button4" Style="{StaticResource ButtonStyle}"/>
<Button Content="Button5" Style="{StaticResource ButtonStyle}"/>
</StackPanel>
</Grid>


WindowのResourceに5つのButtonの共通設定をもったStyleを定義しています。
SetterはPropertyで指定したプロパティにValueで指定した値を設定します。
KeyではこのStyleに名前をつけています。
TargetTypeにはこのStyleを割り当てるコントロールの型を指定します。

5つのButtonにはKeyに設定した名前を指定してこのStyleを適用しています。
このようにすることで同じ記述を複数回書く手間を省く事ができます。
また、修正が必要になったときの修正箇所を一箇所にまとめる事ができます。

実行結果は以下のようになります。
1.jpg
1.jpg

チェックボックスのチェック状態とボタンの有効状態が連動します。

Styleで設定しているプロパティを、そのStyleを適用するコントロール側にも設定できます。
この場合、Styleを適用するコントロール側で設定しているプロパティ値が優先されます。

<Window.Resources>
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="23"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="IsEnabled" Value="{Binding IsChecked, ElementName=ButtonEnabled}"/>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel>
<CheckBox Content="Enabled" x:Name="ButtonEnabled"/>
<Button Content="Button1" Style="{StaticResource ButtonStyle}"/>
<Button Content="Button2" Style="{StaticResource ButtonStyle}"/>
<Button Content="Button3" Style="{StaticResource ButtonStyle}"/>
<Button Content="Button4" Style="{StaticResource ButtonStyle}"/>
<Button Content="Button5" Style="{StaticResource ButtonStyle}" IsEnabled="True"/>
</StackPanel>
</Grid>


5つ目のButtonにはStyleでも設定しているIsEnabledをTrueに設定しています。
5つ目のButtonではIsEnabled=Trueの設定が優先されるので
CheckBoxのON/OFFによらず常に有効状態となります。

実行結果です。
1.jpg

StyleのKeyについてですが、これを指定しない場合
同一xaml内のTargetTypeで指定したコントロール全てにこのStyleが適用されます。
コントロールのStyleプロパティを設定していなくても適用されます。

<Window.Resources>
<Style TargetType="Button">
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="23"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="IsEnabled" Value="{Binding IsChecked, ElementName=ButtonEnabled}"/>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.RowSpan="2">
<CheckBox Content="Enabled" x:Name="ButtonEnabled"/>
<Button Content="Button1"/>
<Button Content="Button2"/>
<Button Content="Button3"/>
<Button Content="Button4"/>
<Button Content="Button5"/>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="OK"/>
<Button Content="Cancel"/>
</StackPanel>
</Grid>


上のサンプルではStyleのKeyを設定していない為、
画面右下に追加したOK、CancelボタンにもこのStyleが適用されます。

1.jpg
1.jpg

基本的にはKeyを設定して使うのがいいと思います。
posted by cw at 10:30| Comment(0) | TrackBack(0) | Style | このブログの読者になる | 更新情報をチェックする

[C# WPF]DataTriggerを使う

今回からTriggerについて解説します。
Triggerを使うとxamlに簡単なロジックを記述できるようになります。

今回紹介するDataTriggerは
Bindingソースの値の変化に合わせて表示を変化させるのに使います。

サンプルを見てみます。
xamlです。

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button Content="実行" Height="23" Margin="5" Click="Execute_Click">
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsRunning}" Value="True">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Content="停止" Height="23" Margin="5" Click="Stop_Click">
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsRunning}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</Grid>


ソースです。

public partial class MainWindow : Window, INotifyPropertyChanged
{
private bool isRunning = false;
public bool IsRunning
{
get { return isRunning; }
set
{
isRunning = value;
OnPropertyChanged("IsRunning");
}
}

public MainWindow()
{
InitializeComponent();

this.DataContext = this;
}

private void Execute_Click(object sender, RoutedEventArgs e)
{
IsRunning = true;
}

private void Stop_Click(object sender, RoutedEventArgs e)
{
IsRunning = false;
}

public event PropertyChangedEventHandler PropertyChanged = (s, e) => { };

private void OnPropertyChanged(string name)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}


xamlでは実行ボタンと停止ボタンを配置しています。
それぞれのボタンのクリックイベントはソースに書いてありますが、
メンバのIsRunningプロパティを切り替えているだけです。

xamlの2つのButtonのStyle部分を見てください。
TriggerはStyleのTriggersの内部に記述します。

DataTriggerはBindingのプロパティ値がValueになった時に内部に記述したSetterを実行します。
プロパティ値がValue以外の場合はStyle.Triggersの外に記述してあるSetterを実行します。
Style.Triggersの外にSetterを記述しない場合はデフォルト値になります。

上記サンプルの実行ボタンは
IsRunningがTrueの時にボタンのIsEnabledがFalseになります。
IsRunningがFalseの時はIsEnabledがTrueになります。
停止ボタンは実行ボタンの逆で
IsRunningがTrueの時にボタンのIsEnabledがTrueになります。
IsRunningがFalseの時はIsEnabledがFalseになります。

実行してみましょう。
2.jpg

実行ボタンを押すとボタンの有効状態が反転します。

1.jpg

停止ボタンを押すと再度ボタンの有効状態が反転します。

Triggerによって画面の動作をxamlに記述できるようになり、
ソースは画面制御を意識する必要がなくなります。
posted by cw at 10:00| Comment(0) | Trigger | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は180日以上新しい記事の投稿がないブログに表示されております。