2010-12-12 54 views
9

因此,願望很簡單,將鼠標光標懸停在按鈕上的按鈕背景變爲LightGreen,將按鈕背景變爲綠色,按下時變爲深綠色。以下XAML是我的第一次嘗試:在Aero上重寫WPF中的按鈕背景

<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 Background="LightGreen"> 
     Hello 
     <Button.Style> 
     <Style TargetType="Button"> 
      <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 Chrome。不想放棄,我嘗試以下放蕩:

... 
    <Button xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" 
      Background="LightGreen"> 
     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="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding 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"> 
      <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> 
... 

現在,我們已經有了在那裏扔整個受詛咒的控制模板從Aero.NormalColor.xaml解除。唉,這沒什麼變化。然後我從Microsoft_Windows_Themes:ButtonChrome元素中刪除兩個屬性(RenderPressedRenderMouseOver)。但是,沒有改變。然後我刪除按鈕的Background屬性的設置,只留下空間聲明中的PresentationFramework.Aero裝配:

... 
<Button xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"> 
    Hello 
... 

最後,我們有進步。我們已經從1/3的要求轉變爲2/3的方式,IsMouseOver和IsPressed可以工作,但是在按鈕的正常狀態(沒有被模糊或者按下)期間沒有淡綠色的背景,因爲我已經移除了從該按鈕的背景屬性,以獲得其他兩個狀態應用和可見。現在,經過這瘋狂的XAML未能得到我們的正常按鈕狀態的淺綠的背景下,我修改樣式扔背景顏色在那裏還有:

<Button xmlns... 
    <ControlTemplate... 
    ... 
    </ControlTemplate> 
    <Button.Style> 
     <Style TargetType="Button"> 
     <!-- ##### Normal state button background added ##### --> 
     <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 = "Background" Value="DarkGreen"/> 
      </Trigger> 
     </Style.Triggers> 
     </Style> 
    </Button.Style> 
    </Button> 

最後,按預期工作。

我是瘋了麼,還是這些(以及更多)你必須通過一個Aero主題來改變一個按鈕的背景顏色在其各種狀態(正常,懸停,按下)?也許,如果我不需要在那裏包括整個dang ButtonTemplate,生活就不會那麼糟糕,只是爲了從中刪除兩個屬性(RenderMouseOverRenderPressed)。

謝謝你的幫助 - 我在智慧的結尾。

更新:但是等待還有更多。

<Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" ... 
    RenderMouseOver="{TemplateBinding IsMouseOver}" 
    RenderPressed="{TemplateBinding IsPressed}" ... 

到:

<Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" ... 
    RenderMouseOver="{Binding IsMouseOver}" 
    RenderPressed="{Binding IsPressed}" ... 

...,還解決了問題(忽略按鈕的樣式觸發的),而不是刪除RenderMouseOver和RenderPressed從控制模板屬性,只需對其進行更改。我認爲問題的根源在於模板綁定在編譯時應用(出於性能原因),而常規綁定則在運行時應用。因此,如果屬性使用模板綁定(即改爲使用來自原始模板的IsMouseOver和IsPressed),則不使用來自各個按鈕的樣式觸發器的綁定。

說了以上的,這裏是Aero的改變按鈕的背景,同時保持其原有的控制模板中的典型的例子:

<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> 

當然,這是假設只有一個按鈕,這樣風格的,否則可以將模板和樣式移出到某個資源部分。此外,沒有觸發按鈕的默認狀態,但它很容易添加到上面的示例中(不要忘記更改控件模板中的RenderDefaulted屬性以使用Binding而不是TemplateBinding)。

如果任何人有關於如何覆蓋用結合只在需要改變控制模板中的兩個屬性的TemplateBinding,而不從航空XAML批發重複整個鍍鉻的定義,我所有的耳朵的任何建議。

回答

2

Button的默認模板使用ButtonChrome,它執行自己的繪圖。如果你想完全擺脫默認外觀,你需要定義你自己的模板,而不需要ButtonChrome。我知道這聽起來很乏味,但你只需要做一次:你可以把你的自定義樣式放在資源字典中,只需要用StaticResource來引用它。請注意,您還可以使用{x:Type Button}作爲樣式的關鍵點(x:Key屬性)將應用樣式應用於應用中的所有按鈕

+0

問題是我只想更改按鈕的背景。 Aero chrome使用按鈕正常狀態的背景按鈕屬性正確處理此問題。但是,這種處理是錯誤的,因爲背景會在鼠標懸停和按鈕被按下時發生變化。在這兩種狀態下,改變按鈕的背景似乎並不容易。這違背了Button中的背景屬性(也許還有其他視覺效果)的全部目的。 – 2010-12-13 01:37:55

+0

Background屬性對所有控件都是通用的,所以無論如何它都會在那裏,但沒有任何保證模板會考慮到它。我可以用Aero主題重現您的問題,以及與Luna主題相似的問題。看來ButtonChrome並沒有考慮到某些州的背景......無論如何,我不認爲標準按鈕鉻的設計是爲了定製它的顏色。如果你想這樣做,只是不要使用鉻...無論如何創建自己的按鈕模板是非常容易的。 – 2010-12-13 09:30:34

+0

從MSDN(Control.Background屬性):Background屬性僅適用於控件的靜止狀態。控件的默認樣式在控件狀態更改時指定其外觀。例如,如果在Button上設置Background屬性,則該按鈕只有在未按下或禁用時才具有該值。如果要創建具有更高級自定義背景的控件,則必須定義控件的樣式。 – 2010-12-13 09:32:52