2010-12-13 1 views
0

ボタンの背景色を、通常のマウスオーバーおよびプレス状態でさまざまな色合いに変更したいとします。私は、私のボタンにButton.Templateという次の奇妙な冗長を追加して、とRenderPressedの属性をTemplateBindingの代わりにBindingの代わりに使うようにしました。その結果、私のトリガー(Button.Style)は実際にはコンパイルされず時間性質はTemplateBindingです。これらの2つの属性をオーバーライドする方法はありますか? XAMLは次のとおりです。コントロールテンプレート全体を繰り返さずに、ボタンのコントロールテンプレート内のTemplateBindingsをBindingsに変更するには

<Window x:Class="ButtonMouseOver.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> 
    <Button> 
     Hello 
     <Button.Template> 
     <ControlTemplate TargetType="{x:Type Button}"> 
      <Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" 
      x:Name="Chrome" Background="{TemplateBinding Background}" 
      BorderBrush="{TemplateBinding BorderBrush}" RenderDefaulted="{TemplateBinding IsDefaulted}" 
      RenderMouseOver="{Binding IsMouseOver}" RenderPressed="{Binding IsPressed}" 
      > 
      <ContentPresenter Margin="{TemplateBinding Padding}" 
              VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
              RecognizesAccessKey="True" 
              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
      </Microsoft_Windows_Themes:ButtonChrome> 
     </ControlTemplate> 
     </Button.Template> 
     <Button.Style> 
     <Style TargetType="Button"> 
      <Setter Property="Background" Value="LightGreen"/> 
      <Style.Triggers> 
      <Trigger Property="IsMouseOver" Value="true"> 
       <Setter Property = "Background" Value="Green"/> 
      </Trigger> 
      <Trigger Property="IsPressed" Value="true"> 
       <Setter Property = "Foreground" Value="DarkGreen"/> 
      </Trigger> 
      </Style.Triggers> 
     </Style> 
     </Button.Style> 
    </Button> 
    </Grid> 
</Window> 

重要な注意を:コントロールテンプレートのみAeroテーマのために必要です。他のテーマについては、Button.Styleだけで仕事をしています。あなたが背景を切り替えるには、スタイルを使用する場合は、ここで行ったよう

+0

私はあなたがこれに対処するためのスタイルを作成せず、あなたが合っているように各ボタンにそれを適用する理由を理解していませんか?私はこの行動に抵抗している作品を見逃しています...?私には標準のボタンスタイルのようです... –

+0

この動作に抵抗している部分は、Aeroクロムです。私はこの事実を強調するためにメモを追加しました。 –

答えて

1

私が考えることのできる最高のものは、ボタンがロードされた後に反射でこれを無効にする動作を追加することです。あなたはこのより良いするよりも、再テンプレートにそれを好きかどうかは知りませんが、PresentationFramework.Aeroとその再利用可能なを含める必要はありません

<Button behaviors:DisableButtonChromeBehavior.DisableButtonChrome="True" 
     ...> 
    <Button.Style> 
     <Style TargetType="Button"> 
      <Setter Property="Background" Value="LightGreen"/> 
      <Style.Triggers> 
       <Trigger Property="IsMouseOver" Value="true"> 
        <Setter Property="Background" Value="Green"/> 
       </Trigger> 
       <Trigger Property="IsPressed" Value="true"> 
        <Setter Property="Foreground" Value="DarkGreen"/> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </Button.Style> 
</Button> 

DisableButtonChromeBehavior

public static class DisableButtonChromeBehavior 
{ 
    public static readonly DependencyProperty DisableButtonChromeProperty = 
     DependencyProperty.RegisterAttached 
     (
      "DisableButtonChrome", 
      typeof(bool), 
      typeof(DisableButtonChromeBehavior), 
      new UIPropertyMetadata(false, OnDisableButtonChromePropertyChanged) 
     ); 
    public static bool GetDisableButtonChrome(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(DisableButtonChromeProperty); 
    } 
    public static void SetDisableButtonChrome(DependencyObject obj, bool value) 
    { 
     obj.SetValue(DisableButtonChromeProperty, value); 
    } 
    private static void OnDisableButtonChromePropertyChanged(DependencyObject dpo, 
                  DependencyPropertyChangedEventArgs e) 
    { 
     Button button = dpo as Button; 
     if (button != null) 
     { 
      if ((bool)e.NewValue == true) 
      { 
       button.Loaded += OnButtonLoaded; 
      } 
      else 
      { 
       button.Loaded -= OnButtonLoaded; 
      } 
     } 
    } 
    private static void OnButtonLoaded(object sender, RoutedEventArgs e) 
    { 
     Button button = sender as Button; 
     Action action =() => 
      { 
       object buttonChrome = VisualTreeHelper.GetChild(button, 0); 
       Type type = buttonChrome.GetType(); 
       PropertyInfo propertyInfo = type.GetProperty("RenderMouseOver"); 
       if (propertyInfo != null) 
       { 
        propertyInfo.SetValue(buttonChrome, false, null); 
        propertyInfo = type.GetProperty("RenderPressed"); 
        propertyInfo.SetValue(buttonChrome, false, null); 
        propertyInfo = type.GetProperty("RenderDefaulted"); 
        propertyInfo.SetValue(buttonChrome, false, null); 
       } 
      }; 
     button.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle); 
    } 
} 

更新
また、再利用できない短い方法もあります。これをコードの背後で行うだけです。それ以外

private void Button_Loaded(object sender, RoutedEventArgs e) 
{ 
    Button button = sender as Button; 
    object buttonChrome = VisualTreeHelper.GetChild(button, 0); 
    PropertyInfo renderMouseOverInfo = buttonChrome.GetType().GetProperty("RenderMouseOver"); 
    if (renderMouseOverInfo != null) 
    { 
     renderMouseOverInfo.SetValue(buttonChrome, false, null); 
    } 
} 

または(あなたがエアロなどの気にしない場合)

<Button ...> 
    <Button.Resources> 
     <Style TargetType="Microsoft_Windows_Themes:ButtonChrome"> 
      <EventSetter Event="Loaded" Handler="ButtonChrome_Loaded"/> 
     </Style> 
    </Button.Resources> 

void ButtonChrome_Loaded(object sender, RoutedEventArgs e) 
{ 
    ButtonChrome buttonChrome = sender as ButtonChrome; 
    if (buttonChrome != null) 
    { 
     buttonChrome.RenderMouseOver = false; 
     buttonChrome.RenderPressed = false; 
    } 
} 

、私はあなたがあなた自身を指摘溶液(再テンプレート)以外のアウトを持っていないと思います。

+0

おっと、これはうまくいくとは思うが、XAMLのクロムのすべてを含むよりも "冗長"だ。 –

+0

あなたは最終的な解決策を見せている!あまりにもXAMLを介して行うことはできません悪い... –

0

、明示的背景プロパティを設定することはできません。

<Button Background="LightGreen"> 

これは、あなたが設定されたすべてのスタイルを上書きします。これを代わりに試してみてください:

これで、もっと使いたい場合を除き、ボタンテンプレートを削除することができます。

あなたはエアロナンセンスを取り除くしたい場合は、そうのようなテンプレートを置き換える:

<Button.Template> 
    <ControlTemplate TargetType="{x:Type Button}"> 
     <Border SnapsToDevicePixels="true" x:Name="Chrome" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"> 
     <ContentPresenter Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
     </Border> 
    </ControlTemplate> 
    </Button.Template> 

ここでの欠点は、あなたがエアロをしたくない場合、あなたはそれのいずれかを取得しないで、あなたはあなたのテンプレートで最初から始めなければなりません。

+0

私の考えは、私はその見落としを訂正しました。ただし、あなたのソリューションはAeroのテーマでは機能せず、コントロールテンプレートもまだ必要です。 –

+0

@Michael:すべてのオペレーティングシステムでAeroテーマを使用する予定ですか?その場合、WPFは現在のWindows OSの感覚を使用するように設計されているため、Aeroを強制的に使用してテンプレートを上書きし、Aeroリソースを使用する方法はありません。 – poindexter12

+0

いいえ、エアロが使用されているときに、効果的な方法でボタンの背景色を変更する方法を考えています。ボタンスタイル(エアロ用)を設定するだけでは機能しません。 –

関連する問題