WPF'de Düğme MouseOver için Arka Planı nasıl değiştirirsiniz?


93

Sayfamda bu XAML ile bir düğme var:

<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Bottom" 
    Width="50" Height="50" HorizontalContentAlignment="Left" 
    BorderBrush="{x:Null}" Foreground="{x:Null}" Margin="50,0,0,0">
    <Button.Style>
        <Style TargetType="Button">
            <Setter Property="Background" Value="Green"/>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="Red"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

Ancak fareyi düğmenin üzerine getirdiğimde, düğmenin arka planı varsayılan pencere gri arka planına dönüşüyor.
Sorun ne?

Bu, fareyle üzerine gelmeden önceki ve sonraki düğme resmidir:
Önce:
Önce
Sonra:
Sonra


Ancak, görüntüyü başlatmanız Forward-48.pngve aynı şekilde değiştirmek için IsMouseOver'ı tetiklemeniz gerekir Forward-48.png. Kodunuzu farklı resimlerle kullanmaya çalışıyorum ve her şey yolunda gitti.
Anatoliy Nikolaev

1
@anatoliy: Çalışmıyor.
Sepehr Mohammadi

Varsayılan renginiz sonra mı? Başka bir yerde değiştirmediğiniz / düğme arka planını ayarlamadığınız herhangi bir yer var mı? Kodunuz iyi çalışıyor.
Anatoliy Nikolaev

Yanıtlar:


175

Varsayılan MouseOverdavranışı kaldırmak Buttoniçin ControlTemplate,. Tanımınızı Styleaşağıdaki şekilde değiştirmek hile yapmalıdır:

<Style TargetType="{x:Type Button}">
    <Setter Property="Background" Value="Green"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border Background="{TemplateBinding Background}" BorderBrush="Black" BorderThickness="1">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="Red"/>
        </Trigger>
    </Style.Triggers>
</Style>

DÜZENLEME: Birkaç yıl gecikti, ancak aslında sınır fırçasını orada bulunan sınırın içine yerleştirebiliyorsunuz. Dikkat edildiyse idk ama öyle görünmüyor ...


1
Bu işe yarıyor, ancak Sınırlar düğmesi kaybolacak! Düğmenin etrafına bir <Border BorderBrush = "DarkGray" BorderThickness = "1"> öğesi koymak gerekiyordu.
Venugopal M

4
@CF bunun nedeni, standart Düğme stilinin içinde tetikleyicilere sahip olmasıdır ControlTemplate, bu nedenle OP'nin Styletetikleyicilerini geçersiz kılarlar .
torvin

1
@torvin Bu çok ters görünüyor! Neden kullanıcı tanımlı bir tetikleyici varsayılan olarak geçersiz kılınmalıdır? Hiyerarşiyi anlıyorum, ControlTemplate Stil'in üstünde, ancak bunun gibi temel ayarları geçersiz kılmanın neden bu kadar zor olduğunu anlamıyorum.
Fuselight

@Fuselight, içindeki tetik ControlTemplatetemelde ' BackgroundRenge uygun olarak kenarlığı boya' diyor . Ve eğer fare düğmenin üzerindeyse - bunun yerine bu sınırı bu renge boyayın ', oysa stilde Backgroundtemeldeki kenarlık rengine değil, yalnızca renge erişebilirsiniz . Yine de işaret ettiğinizi görüyorum, WPF stili arzulanan çok şey bırakıyor ...
torvin

Bu, saydam bir arka plana sahip bir görüntü kullanırken, rollover'da görünen mavi kutuyu kaldırmanın ek avantajına sahiptir. Benim durumumda sınırı istemedim, bu yüzden BorderThickness'ı 0'a ayarlayın.
Chuck Savage

22

Şimdiye kadarki tüm cevaplar, varsayılan düğme davranışını tamamen başka bir şeyle değiştirmeyi içeriyor. Ancak IMHO , bir XAML öğesi için mevcut, varsayılan şablonu düzenleyerek yalnızca ilgilendiğiniz bölümü değiştirmenin mümkün olduğunu anlamak yararlı ve önemlidir .

Bir WPF düğmesindeki fareyle üzerine gelme etkisinin ele alınması durumunda, bir WPF Buttonöğesindeki görünümdeki değişikliğe , özelliği temel alan ve en üst düzey öğenin ve özelliklerini ayarlayan Triggervarsayılan stildeki bir neden olur. kontrol şablonunda. Öğenin arka plan altında olduğunu değişiyor, böylece öğenin arka özelliği görülmesini hover efekti engellemez.ButtonIsMouseOverBackgroundBorderBrushBorderButtonBorderButton.Background

Biraz çaba sarf ederek, bu davranışı kendi ayarlayıcınızla geçersiz kılabilirsiniz, ancak etkilemeniz gereken öğe şablonda olduğundan ve kendi XAML'inizde doğrudan erişilebilir olmadığından, bu yaklaşım zor ve IMHO aşırı karmaşık olacaktır.

Başka bir seçenek olarak grafiği kullanmak yapmak olacaktır Contentiçin Buttonyerine Background. Grafik üzerinde ek içeriğe ihtiyacınız varsa, bunları içerikte Griden üst düzey nesne olarak bir ile birleştirebilirsiniz .

Ancak, kelimenin tam anlamıyla yalnızca üzerine gelme efektini tamamen devre dışı bırakmak istiyorsanız (yalnızca gizlemek yerine), Visual Studio XAML Tasarımcısı'nı kullanabilirsiniz:

  1. XAML'inizi düzenlerken, "Tasarım" sekmesini seçin.
  2. In "Tasarım" sekmesine, bu durumun etkili devre dışı bırakmak istediğiniz düğmeyi bulun.
  3. Bu düğmeye sağ tıklayın ve "Şablonu Düzenle / Bir Kopyasını Düzenle ..." seçeneğini seçin . Yeni şablon kaynağının yerleştirilmesini istediğiniz yere ulaştığınız bilgi isteminde seçin. Bu hiçbir şey yapmıyor gibi görünecek, ancak aslında Tasarımcı söylediğiniz yerde yeni kaynaklar eklemiş ve düğme öğenizi, bu kaynakları düğme şablonu olarak kullanan stile başvurmak için değiştirmiş olacaktır.
  4. Şimdi gidip bu stili düzenleyebilirsiniz. En kolay şey, öğeyi silmek veya yorumlamaktır (örneğin Ctrl+ E, C) <Trigger Property="IsMouseOver" Value="true">...</Trigger>. Elbette, bu noktada şablonda istediğiniz değişikliği yapabilirsiniz.

İşiniz bittiğinde düğme stili şuna benzer:

<p:Style x:Key="FocusVisual">
  <Setter Property="Control.Template">
    <Setter.Value>
      <ControlTemplate>
        <Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</p:Style>
<SolidColorBrush x:Key="Button.Static.Background" Color="#FFDDDDDD"/>
<SolidColorBrush x:Key="Button.Static.Border" Color="#FF707070"/>
<SolidColorBrush x:Key="Button.MouseOver.Background" Color="#FFBEE6FD"/>
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="#FF3C7FB1"/>
<SolidColorBrush x:Key="Button.Pressed.Background" Color="#FFC4E5F6"/>
<SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>
<SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
<SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
<p:Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
  <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
  <Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
  <Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
  <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
  <Setter Property="BorderThickness" Value="1"/>
  <Setter Property="HorizontalContentAlignment" Value="Center"/>
  <Setter Property="VerticalContentAlignment" Value="Center"/>
  <Setter Property="Padding" Value="1"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
          <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Border>
        <ControlTemplate.Triggers>
          <Trigger Property="IsDefaulted" Value="true">
            <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
          </Trigger>
          <!--<Trigger Property="IsMouseOver" Value="true">
            <Setter Property="Background" TargetName="border" Value="{StaticResource Button.MouseOver.Background}"/>
            <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.MouseOver.Border}"/>
          </Trigger>-->
          <Trigger Property="IsPressed" Value="true">
            <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Pressed.Background}"/>
            <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border}"/>
          </Trigger>
          <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Disabled.Background}"/>
            <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border}"/>
            <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</p:Style>

(Not: p:XML ad alanı niteliklerini gerçek kodda atlayabilirsiniz … Bunları burada sağlıyorum çünkü Yığın Taşması XML kod biçimlendiricisi <Style/>XML ad alanıyla tam olarak nitelenmiş bir ada sahip olmayan öğelerle karıştırılır .)

Aynı stili diğer düğmelere de uygulamak istiyorsanız, yalnızca sağ tıklayıp "Şablonu Düzenle / Kaynağı Uygula" yı seçip ilk düğme için eklediğiniz stili seçebilirsiniz. XAML'deki öğelere varsayılan bir stil uygulamak için normal teknikleri kullanarak, bu stili tüm düğmeler için varsayılan stil bile yapabilirsiniz.


6
Çok teşekkürler. Burada kabul edilebilir tek cevap bu
Jared Beach

13

Bu benim için iyi çalıştı.

Düğme Stili

<Style x:Key="TransparentStyle" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border>
                    <Border.Style>
                        <Style TargetType="{x:Type Border}">
                            <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" Value="DarkGoldenrod"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                    <Grid Background="Transparent">
                        <ContentPresenter></ContentPresenter>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Buton

<Button Style="{StaticResource TransparentStyle}" VerticalAlignment="Top" HorizontalAlignment="Right" Width="25" Height="25"
        Command="{Binding CloseWindow}">
    <Button.Content >
        <Grid Margin="0 0 0 0">
            <Path Data="M0,7 L10,17 M0,17 L10,7" Stroke="Blue" StrokeThickness="2" HorizontalAlignment="Center" Stretch="None" />
        </Grid>
    </Button.Content>
</Button>

Notlar

  • Düğme, bir pencereyi kapatmak için kullanılana çok benzer, küçük bir mavi çarpı işareti görüntüler.
  • Izgaranın arka planını "Şeffaf" olarak ayarlayarak, bir hitest ekler, yani fare düğmenin üzerinde herhangi bir yerdeyse, o zaman çalışacaktır. Bu etiketi çıkarırsanız düğme yalnızca, fare simgedeki vektör çizgilerinden birinin üzerindeyse yanar (bu pek kullanışlı değildir).

1
Bu harika bir cevap, ama sadece üzerine gelmeden, fareyle üzerine gelindiğinde Strokerengi değiştirmeye ne dersiniz ? BorderPath
Nateous

1
x:Key="TransparentStyle"Oraya gitmem için bu kısım ve kullanım önemliydi ... Teşekkürler!
nrod

6

Sadece kullanmakta olduğum ResourceDictionary'den düğme stilimi paylaşmak istiyorum. OnHover arka planını stil tetikleyicilerinde özgürce değiştirebilirsiniz. " ColorAnimation To = * istediğiniz BG (yani # FFCEF7A0)". Ayrıca, mouseOver durumundan sonra düğme KŞ'si otomatik olarak orijinal KŞ'ine geri dönecektir. Geçişin ne kadar hızlı olacağını bile ayarlayabilirsiniz.

Kaynak Sözlüğü

<Style x:Key="Flat_Button" TargetType="{x:Type Button}">
    <Setter Property="Width" Value="100"/>
    <Setter Property="Height" Value="50"/>
    <Setter Property="Margin" Value="2"/>
    <Setter Property="FontFamily" Value="Arial Narrow"/>
    <Setter Property="FontSize" Value="12px"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="Cursor" Value="Hand"/>
    <Setter Property="Foreground">
        <Setter.Value>
            <SolidColorBrush Opacity="1" Color="White"/>
        </Setter.Value>
    </Setter>
    <Setter Property="Background" >
        <Setter.Value>
            <SolidColorBrush Opacity="1" Color="#28C2FF" />
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">

                <Border x:Name="border"
                         SnapsToDevicePixels="True"
                         BorderThickness="1"
                         Padding="4,2"
                         BorderBrush="Gray"
                         CornerRadius="3"
                         Background="{TemplateBinding Background}">
                    <Grid>
                        <ContentPresenter 
                        Margin="2"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        RecognizesAccessKey="True" />

                    </Grid>
                </Border>

            </ControlTemplate>
        </Setter.Value>
    </Setter>

    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="true">
            <Trigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard>
                        <ColorAnimation To="#D2F898"
                                        Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" 
                                        FillBehavior="HoldEnd" Duration="0:0:0.25" AutoReverse="False" RepeatBehavior="1x"/>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.EnterActions>

            <Trigger.ExitActions>
                <BeginStoryboard>
                    <Storyboard>
                        <ColorAnimation
                                            Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)" 
                                            FillBehavior="HoldEnd" Duration="0:0:0.25" AutoReverse="False" RepeatBehavior="1x"/>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.ExitActions>

        </Trigger>


    </Style.Triggers>
</Style>

tek yapman gereken tarzı aramak.

Örnek Uygulama

<Button Style="{StaticResource Flat_Button}" Height="Auto"Width="Auto">  
     <StackPanel>
     <TextBlock Text="SAVE" FontFamily="Arial" FontSize="10.667"/>
     </StackPanel>
</Button>

3

ControlTemplate kullanan ve bir animasyon efektine sahip olan biraz daha zor bir cevap ( https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/customizing-the-appearance-of-an-existing- adresinden uyarlanmıştır. kontrol )

Kaynak sözlüğünüzde, düğmeniz için şuna benzer bir kontrol şablonu tanımlayın:

<ControlTemplate TargetType="Button" x:Key="testButtonTemplate2">
    <Border Name="RootElement">
        <Border.Background>
            <SolidColorBrush x:Name="BorderBrush" Color="Black"/>
        </Border.Background>

        <Grid Margin="4" >
            <Grid.Background>
                <SolidColorBrush x:Name="ButtonBackground" Color="Aquamarine"/>
            </Grid.Background>
            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="4,5,4,4"/>
        </Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Normal"/>
                <VisualState x:Name="MouseOver">
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="Color" To="Red"/>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Pressed">
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="Color" To="Red"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Border>
</ControlTemplate>

XAML'nizde düğmeniz için yukarıdaki şablonu aşağıdaki gibi kullanabilirsiniz:

Düğmenizi tanımlayın

<Button Template="{StaticResource testButtonTemplate2}" 
HorizontalAlignment="Center" VerticalAlignment="Center" 
Foreground="White">My button</Button>

Umarım yardımcı olur


0

Değiştir düğmesi stili için

1: kaynak stillerini tanımlayın

<Window.Resources>

    <Style x:Key="OvergroundIn" TargetType="Button">

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid Background="#FF16832F">
                        <ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">

                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid Background="#FF06731F">
                                <ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>

            </Trigger>
        </Style.Triggers>

    </Style>

    <Style x:Key="OvergroundOut" TargetType="Button">

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid Background="#FFF35E5E">
                        <ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">

                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid Background="#FFE34E4E">
                                <ContentPresenter TextBlock.Foreground="White" TextBlock.TextAlignment="Center" Margin="0,8,0,0" ></ContentPresenter>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>

            </Trigger>
        </Style.Triggers>

    </Style>


</Window.Resources>

2. tanımlama düğmesi kodu

                           <Border Grid.Column="2" BorderBrush="LightGray" BorderThickness="2" CornerRadius="3" Margin="2,2,2,2"  >
                                <Button Name="btnFichar" BorderThickness="0" Click="BtnFichar_Click">
                                    <Button.Content>
                                        <Grid>
                                            <TextBlock Margin="0,7,0,7" TextAlignment="Center">Fichar</TextBlock> 
                                        </Grid>
                                    </Button.Content>
                                </Button>
                            </Border>

Arkasındaki 3. kod

    public void ShowStatus()
    {
        switch (((MainDto)this.DataContext).State)
        {
            case State.IN:
                this.btnFichar.BorderBrush = new SolidColorBrush(Color.FromRgb(243, 94, 94));
                this.btnFichar.Style = Resources["OvergroundIn"] as Style;
                this.btnFichar.Content = "Fichar Salida";
                break;

            case State.OUT:
                this.btnFichar.BorderBrush = new SolidColorBrush(Color.FromRgb(76, 106, 83));
                this.btnFichar.Style = Resources["OvergroundOut"] as Style;
                this.btnFichar.Content = "Fichar Entrada";
                break;

        }
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.