2010-12-12 4 views
9

그래서 단추의 배경을 LightGreen으로 변경하고 녹색을 마우스 커서로 가리키면 녹색으로, 변경하면 DarkGreen을 누르면됩니다. 다음 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> 

그러나 이것은 아예 작동하지 않습니다. 우리는 목표로가는 길의 1/3에 불과합니다. 네, 버튼이 연두색이됩니다. 그러나 마우스를 가져 가거나 누르는 즉시 해당 버튼 상태에 대해 표준 Aero 크롬을 얻습니다.

... 
    <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)을 제거합니다. 여전히 변화가 없습니다. 나는 다음 PresentationFramework.Aero 어셈블리에 대한 바로 네임 스페이스 선언을 떠나, 버튼의 Background 속성의 설정을 제거 :

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

마지막으로, 우리는 진전이있다. IsMouseOver 및 IsPressed가 작동하면서 버튼의 정상 상태 (마우스 오버 또는 누르지 않음) 중에 밝은 녹색 배경이 나타나지 않았습니다. 삭제 한 이후로 1/3에서 2/3로 변경되었습니다. 버튼의 Background 속성을 사용하여 다른 두 상태를 적용하고 표시 할 수 있습니다. 이 광란의 XAML은 우리에게 일반 버튼 상태에 대한 LightGreen 배경의 취득에 실패 후 지금, 나는 거기뿐만 아니라에 배경 색상을 던져 스타일을 수정 의도 한대로

<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 테마를 사용하여 여러 가지 상태 (정상 상태, 넘어서 놓은 상태, 누른 상태) 중 하나에서 버튼의 배경색을 변경하려면 미쳐야합니까? 아마도 두 개의 속성 (RenderMouseOverRenderPressed)을 제거하기 위해 전체 버튼 ButtonTemplate을 포함 할 필요가 없다면 인생이 그리 좋지 않을 것입니다.

도움 주셔서 감사합니다. 나는 재치가있다.

업데이트 :하지만 더 기다려주세요.

<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가 대신 사용됨)을 사용하는 경우 개별 단추에서 스타일 트리거의 바인딩이 사용되지 않습니다.

여기에 원래 컨트롤 템플릿을 유지하면서 에어로에서 버튼의 배경을 변경하기위한 표준적인 예는, 위의 모든 말했다 데 :

이 단 하나의 버튼이 너무 스타일된다고 가정 물론이다
<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> 

, 그렇지 않으면 템플릿과 스타일을 어딘가에있는 리소스 섹션으로 옮길 수 있습니다. 또한 단추의 기본 상태에 대한 트리거는 없지만 위 예제에 쉽게 추가됩니다 (TemplateBinding 대신 Binding을 사용하도록 컨트롤 템플릿의 RenderDefaulted 특성을 변경하는 것을 잊지 마십시오).

사람이 비행기 XAML 도매에서 전체 크롬 정의를 반복하지 않고, 나는 모든 귀를 얼마나에 재정 변경해야 컨트롤 템플릿에만 두 속성에 대한 바인딩과 TemplateBinding에 어떤 제안이있는 경우.

답변

2

Button의 기본 템플릿은 자체 드로잉을 수행하는 ButtonChrome을 사용합니다. 기본 모양을 완전히 없애려면 ButtonChrome없이 자신 만의 템플릿을 정의해야합니다. 지루한 것처럼 들리지만 한 번만하면됩니다. 사용자 정의 스타일을 리소스 사전에 넣고 StaticResource으로 참조하면됩니다. 스타일의 키로 {x:Type Button}을 사용하여 앱의 모든 버튼에 스타일을 적용 할 수도 있습니다 (x:Key 속성)

+0

문제는 버튼의 배경을 변경하려는 것입니다. Aero 크롬은 버튼의 정상 상태에 대한 배경 버튼 속성을 사용하여 올바르게 처리합니다. 그러나이 처리는 잘못되었습니다. 마우스 오버시 마우스 오른쪽 단추로 배경이 바뀌고 단추를 눌렀을 때입니다. 이 두 가지 상태에서 버튼의 배경을 변경하는 쉬운 방법은 없습니다. 이것은 Button에 Background 속성을 갖는 모든 목적을 무효화합니다 (그리고 아마도 다른 시각적 요소). –

+0

Background 속성은 모든 컨트롤에 공통적으로 적용되므로 어쨌든 존재하지만 템플릿에서 고려해야 할 사항은 없습니다. 나는 Aero 테마로 문제를 재현 할 수 있고 Luna 테마로도 비슷한 문제를 재현 할 수있다. ButtonChrome이 특정 주에서 배경을 고려하지 않는 것 같습니다 ... 어쨌든 표준 버튼 크롬은 색상을 맞춤 설정하도록 설계되지 않았습니다. 원한다면 크롬을 사용하지 마십시오. 어쨌든 자신 만의 버튼 템플릿을 만드는 것은 매우 쉽습니다. –

+0

MSDN (Control.Background 속성)의 경우 : Background 속성은 컨트롤의 휴식 상태에만 적용됩니다. 컨트롤의 기본 스타일은 컨트롤의 상태가 변경 될 때 모양을 지정합니다. 예를 들어, Button에 Background 속성을 설정하면 버튼은 눌려지지 않았거나 비활성화 된 경우에만 해당 값을가집니다. 배경의 고급 사용자 지정이있는 컨트롤을 만들려면 컨트롤의 스타일을 정의해야합니다. –

관련 문제