none
System.Windows.Controls.Buttonを画像ボタンにする方法 RRS feed

  • 質問

  • 現在、System.Windows.ControlsのButtonを使ったボタンを画像ボタンにしようとしています。

    色々調べた結果,

    Button load_button = new Button();
    load_button.Background = new ImageBrush(new BitmapImage(
                    new Uri(@"./icon/load.png", UriKind.Relative)));
    load_button.Click += new RoutedEventHandler(load_button_Click);

    とすることで、画像ボタンにする事は出来ました。

    ただし、ボタンそのものは画像になりましたが、画像左のように枠線が表示されてしまいます。

    また、マウスオーバーすると画像右のように(マウスが写ってないですが)元のボタンに戻ってしまいます。

    XAMLにControlTemplateを用意し、BorderBrushをα値が0になるように指定すると、輪郭線が消えるのと同時に画像も表示されなくなり、標準の灰色のボタンになってしまいます。

    その時のコードはこんな感じです。

    XAML

    <Window.Resources>
            <ControlTemplate x:Key="ButtonTemplate">
                <Button BorderBrush="#00000000" />
            </ControlTemplate>
     </Window.Resources>

    csファイル

    Button save_button = new Button();
    save_button.Template = (ControlTemplate)window.Resources["ButtonTemplate"];
    save_button.Background = new ImageBrush(new BitmapImage(
                    new Uri(@"./icon/save.png", UriKind.Relative)));

    輪郭線を消して画像を表示し、かつマウスオーバーしても変化しないようなボタンを作るにはどのようにすればいいのでしょうか。

    2012年10月22日 10:19

回答

  • 単純に画像そのものをボタンにしたいのでしたら、ControlTemplateで、ContentPresenterだけ置くようにしてButtonのContentにImageをおくとかどうでしょう??


    かずき Blog:http://d.hatena.ne.jp/okazuki/

    • 回答としてマーク blue_wind_ 2012年10月23日 11:34
    2012年10月22日 11:17
  • かずきさんの返信内容で(わかる人には)ほぼ「終了~」なのですが、挙げられたコードを見る限りそれだけだと厳しいように思えるのでコードを書いてみました。

    <Window x:Class="WpfApplication6.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
    
            <!--Buttonの内部に画像を配置する例-->
            <Button Grid.Row="0" Content="C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg" Click="Button_Click">
                <Button.ContentTemplate>
                    <DataTemplate>
                        <Image Source="{Binding}"/>
                    </DataTemplate>                
                </Button.ContentTemplate>
            </Button>
    
            <!--Buttonそのものを画像に置き換える例-->
            <Button Grid.Row="1" Content="C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg" Click="Button_Click">
                <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <ContentPresenter>
                            <ContentPresenter.ContentTemplate>
                                <DataTemplate>
                                    <Image Source="{Binding}"/>
                                </DataTemplate>
                            </ContentPresenter.ContentTemplate>
                        </ContentPresenter>
                    </ControlTemplate>
                </Button.Template>
            </Button>
        </Grid>
    </Window>
    

    上のボタンはボタンの内部にコンテンツとして画像を配置する例、下のボタンはボタンそのものを画像でオーバーラップする例です。
    上の例はButton(ContentControl派生)のContentに画像を、Contentの表示形式(ContentTemplate)にImageコントロールを指定しています。
    かずきさんが指摘されているのは下の例です。Button.Templateをまるごと上書きするというものです。
    ただし下の例の場合、Template上書き=オーバーマウス時・クリック時の動作も上書きされ未定義状態になりますので、クリックしたかどうかよくわからんという状態にはなります。

    本来のButtonコントロールのTemplateはちょっと特殊で、ButtonChromeという装飾担当のコントロールの上にContentPresenterが乗っかっている格好になっています。
    で、オーバーマウスやクリックのイベント時にTriggerでButtonChromeの装飾を遷移させることで視覚効果を生み出しています。
    ですので真っ当にやるのであれば、Buttonの既定テンプレートを元にカスタマイズするのが筋なのですが、大変めんどくさいのでそこまでやるかは状況次第だと思います。

    • 回答としてマーク blue_wind_ 2012年10月23日 11:19
    2012年10月22日 14:36

すべての返信

  • 単純に画像そのものをボタンにしたいのでしたら、ControlTemplateで、ContentPresenterだけ置くようにしてButtonのContentにImageをおくとかどうでしょう??


    かずき Blog:http://d.hatena.ne.jp/okazuki/

    • 回答としてマーク blue_wind_ 2012年10月23日 11:34
    2012年10月22日 11:17
  • かずきさんの返信内容で(わかる人には)ほぼ「終了~」なのですが、挙げられたコードを見る限りそれだけだと厳しいように思えるのでコードを書いてみました。

    <Window x:Class="WpfApplication6.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
    
            <!--Buttonの内部に画像を配置する例-->
            <Button Grid.Row="0" Content="C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg" Click="Button_Click">
                <Button.ContentTemplate>
                    <DataTemplate>
                        <Image Source="{Binding}"/>
                    </DataTemplate>                
                </Button.ContentTemplate>
            </Button>
    
            <!--Buttonそのものを画像に置き換える例-->
            <Button Grid.Row="1" Content="C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg" Click="Button_Click">
                <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <ContentPresenter>
                            <ContentPresenter.ContentTemplate>
                                <DataTemplate>
                                    <Image Source="{Binding}"/>
                                </DataTemplate>
                            </ContentPresenter.ContentTemplate>
                        </ContentPresenter>
                    </ControlTemplate>
                </Button.Template>
            </Button>
        </Grid>
    </Window>
    

    上のボタンはボタンの内部にコンテンツとして画像を配置する例、下のボタンはボタンそのものを画像でオーバーラップする例です。
    上の例はButton(ContentControl派生)のContentに画像を、Contentの表示形式(ContentTemplate)にImageコントロールを指定しています。
    かずきさんが指摘されているのは下の例です。Button.Templateをまるごと上書きするというものです。
    ただし下の例の場合、Template上書き=オーバーマウス時・クリック時の動作も上書きされ未定義状態になりますので、クリックしたかどうかよくわからんという状態にはなります。

    本来のButtonコントロールのTemplateはちょっと特殊で、ButtonChromeという装飾担当のコントロールの上にContentPresenterが乗っかっている格好になっています。
    で、オーバーマウスやクリックのイベント時にTriggerでButtonChromeの装飾を遷移させることで視覚効果を生み出しています。
    ですので真っ当にやるのであれば、Buttonの既定テンプレートを元にカスタマイズするのが筋なのですが、大変めんどくさいのでそこまでやるかは状況次第だと思います。

    • 回答としてマーク blue_wind_ 2012年10月23日 11:19
    2012年10月22日 14:36
  • ありがとうございます、本気でやろうとすると凄いめんどくさいんですね…(^_^;

    今回はコード側から動的にボタンを追加したいため、XAMLに書いた設定ををコード側から読み込むことで実現できました。

    上の例だと<Button.ContentTemplate>部分だけを書く方法がわからなかったため、お二人に教わった下の方式を使い、ControlTemplate部分のみをXAMLに書いて読み込んでいます。

    確かにおっしゃっているようにクリック時によく解らないという問題がありますが、そこは目をつぶることにします。

    どうもありがとうございました。


    コード側

                 //再生ボタン
                Button save_button = new Button();
                save_button.Content = @"C:\\load.png";
                save_button.Template = (System.Windows.Controls.ControlTemplate )pane.Resources["testButton"];
    

    XAML側

        <Window.Resources>
            <ControlTemplate TargetType ="Button" x: Key="testButton">
                <ContentPresenter>
                    <ContentPresenter.ContentTemplate>
                        <DataTemplate>
                            <Image Source ="{Binding}"/>
                        </DataTemplate>
                    </ContentPresenter.ContentTemplate>
                </ContentPresenter>
            </ControlTemplate>
    
        </Window.Resources>
    

    2012年10月23日 11:35