2017-11-11 67 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に示されている3つのマウスのスクリーンショット。
  2. コードを使用すると、2つのイベントMouseMoveとMouseLeaveが各ボタンに強制的に作成されます。コードなしで、xamlだけを使用し、すべてのコードを1つのファイルに入れて、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

・ファーストの問題は、このために起こります1つのコンポーネントが定義されていないPoint(それが意味するものであれば)。代わりに使用する

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

第2の問題は。まず、スタイルは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'と見なすことをOPに指摘することは有用でしょう。 'NaN'(既定値)である' Width'値に戻すはずです。 –

+0

@PeterDunihoこれは本当ですが、これは道路のどこかで(Pointコンストラクタ内で、または無効なポイントをGradientOriginに割り当てる間に)何らかの例外が発生することに少し驚いていました。多分未定義の座標を指す意味がありますが、私はそれを見ることができません。 – Evk

+0

@PeterDunihoあなたは正しいです。しかし、例外がスローされていないので、値は大丈夫だと思います。次回は気をつけます。 – user1624552

関連する問題