2017-11-11 21 views
0

here과 같이 마우스를 위로 움직이면 내 단추에 방사형 그래디언트 효과를 적용하고 싶습니다. 그래서 나는 나의 버튼 스타일을 정의하는 분리 된 리소스 파일을 가지고있다.WPF : 마우스로 움직이는 방사형 그라데이션이 컨트롤 위로 이동

MyButtonStyle.xaml :

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:local="clr-namespace:MyTestButtons"> 
    <Style TargetType="Button" x:Key="MyButtonStyle"> 
     <!--<Setter Property="Background" Value="Transparent" />--> 
     <Setter Property="TextBlock.TextAlignment" Value="Center" /> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="Button">     
        <Border Name="Border" CornerRadius="0" 
          BorderBrush="#000" BorderThickness="1,1,1,1" 
          Background="{TemplateBinding Background}"> 
         <ContentPresenter x:Name="contentPresenter" 
              ContentTemplate="{TemplateBinding ContentTemplate}" 
              Content="{TemplateBinding Content}" 
              HorizontalAlignment="{TemplateBinding HorizontalAlignment}" 
              Margin="{TemplateBinding Padding}" 
              VerticalAlignment="{TemplateBinding VerticalAlignment}" /> 
        </Border> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

그리고 아래 내 버튼에 적용됩니다.

: 코드 숨김

<Window x:Class="MyTestButtons" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 

    <Window.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="/MyButtonStyle.xaml" /> 
      </ResourceDictionary.MergedDictionaries> 
     </ResourceDictionary> 
    </Window.Resources> 

    <Button Name="btnYes" Content="Yes" 
     Margin="3,5" MinWidth="70" Height="35" 
     Click="Button_Click" Foreground="Black" FontSize="14" 
     Style="{StaticResource MyButtonStyle}" 
     VerticalAlignment="Center" 
     HorizontalAlignment="Stretch" 
     VerticalContentAlignment="Center" 
     HorizontalContentAlignment="Center" 
     MouseMove="btnYes_MouseMove" 
     MouseLeave="btnYes_MouseLeave"> 
    <Button.Background> 
     <RadialGradientBrush x:Name="gradRadial" RadiusX="0.25"> 
      <GradientStop Color="AliceBlue" Offset="0.0"/> 
      <GradientStop Color="LightSteelBlue" Offset="1.0"/> 
     </RadialGradientBrush> 
    </Button.Background> 
    </Button> 
</Window> 

창 :

private void btnYes_MouseMove(object sender, MouseEventArgs e) 
    { 
     Point pt = Mouse.GetPosition(btnYes); 
     gradRadial.GradientOrigin = new Point(pt.X/btnYes.Width, pt.Y/btnYes.Height); 
     gradRadial.Center = gradRadial.GradientOrigin; 
    } 

    private void btnYes_MouseLeave(object sender, MouseEventArgs e) 
    { 
     gradRadial.GradientOrigin = new Point(0.5, 0.5); // Default 
     gradRadial.Center = gradRadial.GradientOrigin; 
    } 

내 문제와 목표는 다음과 같습니다

  1. 방사형 그라데이션이 제대로 적용되지 않습니다. 내 단추의 중앙에 방사형 그래디언트가 표시되고 마우스를 단추 위로 움직이면 방사형 그래디언트는 항상 중앙에 유지되고 방사형 그래디언트는 마우스가 끝나는 원점에서 생성되지 않습니다. 제공되는 link에 표시된 세 마리 마우스의 스크린 샷.
  2. 코드 숨김을 사용하면 두 개의 이벤트 (각 단추에 대해 MouseMove 및 MouseLeave)가 생성됩니다. 난 뒤에 코드없이, 단지 xaml을 사용하여 하나의 파일에 모든 코드를 넣어, 내 스타일 파일 MyButtonStyle.xaml에서하고 싶습니다. 당신은 btnYes.Width 사용

    gradRadial.GradientOrigin = new Point(pt.X/btnYes.Width, pt.Y/btnYes.Height); 
    

    하지만 당신은 버튼이 속성을 설정하지 않으며, 기본적으로는 값 (double.NaN)에 정의되지 않은, 그래서 당신은 종료 :

+1

내가 대답은 # 1을 발행 할 생각 발견을 당신이 제공 한 링크에 이 중요한 세부 사항에 유의하십시오. 또한 마우스가 위에있을 때 버튼의 기본 렌더링을 비활성화해야합니다. 버튼의 컨트롤 템플릿에있는 ButtonChrome 객체의 RenderMouseOver 속성을 False로 변경하면됩니다. ' – pstrjds

+0

@pstrjds ok. 이제 마우스를 스타일 파일에 올려 놓은 상태에서 버튼의 기본 렌더링을 비활성화하려면 어떻게합니까? – user1624552

답변

3

Fisrt 문제는이 때문에 발생 하나의 구성 요소가 정의되지 않은 점 (의미가 무엇이든간에). 대신 사용하십시오

gradRadial.GradientOrigin = new Point(pt.X/btnYes.ActualWidth, pt.Y/btnYes.ActualHeight); 

두 번째 문제는. 첫째, 스타일은 EventSetter을 통해 이벤트 핸들러를 설정할 수 있습니다. 둘째, 자원 사전에는 코드 숨김이있을 수 있습니다. 그래서 당신은 이것을 할 수 있습니다. 먼저 리소스 사전에 클래스를 지정 :

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       x:Class="WpfApplication1.Resources"> 
</ResourceDictionary> 

다음 코드 숨김 정의 :

// this is in namespace WpfApplication1 
partial class Resources : ResourceDictionary { 
    public Resources() { 
     InitializeComponent(); 
    } 

    private void OnMyButtonMouseLeave(object sender, MouseEventArgs e) { 
     var btn = (Button) sender; 
     var gradient = btn.Background as RadialGradientBrush; 
     if (gradient == null) 
      return; 
     gradient.GradientOrigin = new Point(0.5, 0.5); // Default 
     gradient.Center = gradient.GradientOrigin; 
    } 

    private void OnMyButtonMouseMove(object sender, MouseEventArgs e) { 
     var btn = (Button) sender; 
     var gradient = btn.Background as RadialGradientBrush; 
     if (gradient == null) 
      return; 
     Point pt = Mouse.GetPosition(btn); 
     gradient.GradientOrigin = new Point(pt.X/btn.ActualWidth, pt.Y/btn.ActualHeight); 
     gradient.Center = gradient.GradientOrigin; 
    } 
} 

는 그런 스타일의 핸들러를 할당합니다

<Style TargetType="Button" 
     x:Key="MyButtonStyle"> 
    <!-- skipped --> 
    <EventSetter Event="MouseLeave" Handler="OnMyButtonMouseLeave"/> 
    <EventSetter Event="MouseMove" Handler="OnMyButtonMouseMove"/> 
</Style> 
+0

IMHO, 간단히'MouseMove' 핸들러를 디버깅하고'Point'의 값을 검사했다면 그들은'X' 값을'NaN'으로 즉시 보았을 것입니다. (기본값)'NaN '인'Width' 값으로 다시 되돌려 놓았어야합니다. –

+0

@PeterDuniho 사실이지만, 길가 (Point 생성자에서 또는 GradientOrigin에 유효하지 않은 점을 할당하는 중)에서 어딘가에 예외가 발생하지 않는다는 사실에 놀랐습니다. 어쩌면 정의되지 않은 좌표와 관련하여 약간의 의미가있을 수도 있지만 나는 그것을 보지 못했습니다. – Evk

+0

@PeterDuniho 당신 말이 맞아요. 그러나 아무 예외도 던지지 않았기 때문에 가치가 있다고 나는 생각했다. 나는 다음에 조심 할 것이다. – user1624552