XAMLでオーナードローボタン(カスタムドローボタン)の作成

XAMLではもはやオーナードローボタンとかいう言い方はしないかもしれないが作成方法について。



MSDNの”ボタン ControlTemplate の例”に載っているソースコードを下記の場所に全てコピペする

<Application.Resources>
	<ResourceDictionary>
		<!-- ここにソースコードをを全てコピペする -->
	</ResourceDictionary>
</Application.Resources>

あとは必要な箇所を変更すれば良いだけなのだが、MSDNに載っているコードの大部分はブラシの定義なので{StaticResource ・・・}の箇所をYellowとかBlueとかにすればもっとすっきりする。下記は変更したコード。x:Key="brushButton"となっている箇所はブラシによるオーナードローで、x:Key="imageButton"となっている箇所は画像ファイルによるオーナードロー。

	<Application.Resources>
		<ResourceDictionary>
		
			// ボタンをBrushで表示
			<Style TargetType="Button" x:Key="brushButton">
				<Style.Setters>
					<Setter Property="Width" Value="90"/>
					<Setter Property="Height" Value="20"/>
					<!-- TemplateBinding Property=Background としているのでこの色が使用される -->
					<Setter Property="Background" Value="Red"/>	
					<!-- フォーカスを表示しないようにしている -->
					<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
                    			<!--
					<Setter Property="FocusVisualStyle">
						<Setter.Value>
							<Style></Style>
						</Setter.Value>
					</Setter>
                    			-->
					<Setter Property="Template">
						<Setter.Value>
							<ControlTemplate TargetType="Button">
								<Border x:Name="Border" CornerRadius="0" BorderThickness="0" Background="{TemplateBinding Property=Background}">
									<Border.Child>
										<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True"/>
									</Border.Child>		
								</Border>

								<ControlTemplate.Triggers>
									<Trigger Property="IsKeyboardFocused" Value="true">
									</Trigger>
									<Trigger Property="IsDefaulted" Value="true">
									</Trigger>
									<Trigger Property="IsMouseOver" Value="true">
										<Setter TargetName="Border" Property="Background" Value="yellow" />
									</Trigger>
									<Trigger Property="IsPressed" Value="true">
										<Setter TargetName="Border" Property="Background" Value="blue" />
									</Trigger>
									<Trigger Property="IsEnabled" Value="false">
										<Setter TargetName="Border" Property="Background" Value="gray" />
										<Setter Property="Foreground" Value="white"/>
									</Trigger>
								</ControlTemplate.Triggers>
							</ControlTemplate>
						</Setter.Value>
					</Setter>
				</Style.Setters>
			</Style>


			// ボタンをイメージで表示
			<Style TargetType="Button" x:Key="imageButton">
				<Style.Setters>
					<Setter Property="Width" Value="90"/>
					<Setter Property="Height" Value="20"/>

					<!-- フォーカスを表示しないようにしている -->
					<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
					<!--
					<Setter Property="FocusVisualStyle">
						<Setter.Value>
							<x:Null/>
						</Setter.Value>
					</Setter>
					-->
					<!--					
					<Setter Property="FocusVisualStyle">
						<Setter.Value>
							<Style></Style>
						</Setter.Value>
					</Setter>
					-->


					<Setter Property="Template">
						<Setter.Value>
							<ControlTemplate TargetType="Button">
								<Grid>
									<Image x:Name="image" Source="image/normal.png"/>
									<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
								</Grid>

								<ControlTemplate.Triggers>
									<Trigger Property="IsKeyboardFocused" Value="true">
									</Trigger>
									<Trigger Property="IsDefaulted" Value="true">
									</Trigger>
									<Trigger Property="IsMouseOver" Value="true">
										<Setter TargetName="image" Property="Source" Value="image/focus.png" />
									</Trigger>
									<Trigger Property="IsPressed" Value="true">
										<Setter TargetName="image" Property="Source" Value="image/select.png" />
									</Trigger>
									<Trigger Property="IsEnabled" Value="false">
										<Setter TargetName="image" Property="Source" Value="image/disable.png" />
										<Setter Property="Foreground" Value="white"/>
									</Trigger>
								</ControlTemplate.Triggers>

							</ControlTemplate>
						</Setter.Value>
					</Setter>
				</Style.Setters>
			</Style>
		</ResourceDictionary>
	</Application.Resources>

このボタンを使用するには下記のようにすれば良い

<Button Style="{StaticResource imageButton}">imageButton</Button>

余談としてIsPressedのカスタム処理はControlTemplateを使用しないと無理っぽい。ControlTemplateを使用すると必要な処理は全て記述しなくてはいけないので上記のソースコードのように長たらしくならざるを得ない。


参照
http://msdn.microsoft.com/ja-jp/library/ms753328(VS.80).aspx
http://blogs.wankuma.com/kazuki/archive/2007/10/24/103981.aspx