Как изменить фон для кнопки MouseOver в WPF?

93

У меня есть кнопка на моей странице с этим XAML:

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

Но когда я наводил указатель мыши на кнопку, фон кнопки меняется на серый фон окна по умолчанию.
В чем проблема?

Это изображение кнопки до и после наведения курсора:
До:
Перед
После:
После

Сепер Мохаммади
источник
Но вам нужно запустить изображение Forward-48.pngи запустить IsMouseOver, чтобы изменить его на то же самое Forward-48.png. Я пытаюсь использовать ваш код с разными изображениями, и у меня все работает нормально.
Анатолий Николаев
1
@anatoliy: Это не работает.
Sepehr Mohammadi
После - ваш цвет по умолчанию? Нигде еще ты не меняешь / не ставишь фон кнопки? У меня твой код работает нормально.
Анатолий Николаев

Ответы:

174

Чтобы удалить MouseOverповедение по умолчанию, Buttonвам необходимо изменить файл ControlTemplate. Изменение вашего Styleопределения на следующее должно помочь:

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

РЕДАКТИРОВАТЬ: это опоздание на несколько лет, но вы действительно можете установить кисть границы внутри границы, которая там находится. Идк, если это было указано, но не похоже, что это было ...

Ричард Э
источник
1
Это работает, однако кнопка Границы исчезнет! Пришлось поместить элемент <Border BorderBrush = "DarkGray" BorderThickness = "1"> вокруг кнопки.
Venugopal M
4
@CF причина этого в том, что в стандартном стиле Button есть триггеры внутри ControlTemplate, поэтому они переопределяют Styleтриггеры OP .
Торвин
1
@torvin Это кажется обратным! Почему пользовательские триггеры должны переопределяться по умолчанию? Я понимаю иерархию, ControlTemplate находится выше Style, но я не понимаю, почему должно быть так сложно переопределить такие базовые настройки.
Fuselight
@Fuselight, триггер внутри в ControlTemplateосновном говорит: «Раскрасьте границу в соответствии с Backgroundцветом. А если указатель мыши находится над кнопкой - вместо этого нарисуйте эту границу этим цветом », в то время как в стиле у вас есть доступ только к Backgroundцвету, а не к основному цвету границы. Я вижу, что вы заметили, стиль WPF оставляет желать лучшего ...
Торвин
Это дает дополнительное преимущество, заключающееся в удалении синего поля, которое появляется при наведении курсора при использовании изображения с прозрачным фоном. В моем случае граница мне не нужна, поэтому установите BorderThickness на 0.
Чак Сэвидж
22

Все ответы на данный момент включают полную замену поведения кнопки по умолчанию на что-то другое. Однако, IMHO, полезно и важно понимать, что можно изменить только ту часть, которая вам нужна , путем редактирования существующего шаблона по умолчанию для элемента XAML.

В случае работы с парения эффекта на кнопку WPF, изменение внешнего вида в WPF Buttonэлемента вызвано Triggerв стиле по умолчанию для Button, которое основано на IsMouseOverсобственности и устанавливает Backgroundи BorderBrushсвойства верхнего уровня Borderэлемента в шаблоне управления. В Buttonфоне элемента находится под Borderфоном элемента, поэтому изменение Button.Backgroundсвойства не мешает эффект парения от просмотра.

Приложив некоторые усилия, вы можете переопределить это поведение с помощью своего собственного установщика, но поскольку элемент, на который вам нужно воздействовать, находится в шаблоне и не доступен напрямую в вашем собственном XAML, этот подход будет сложным и, по-моему, чрезмерно сложным.

Другой вариант - использовать графику в качестве Contentэлемента, Buttonа не элемента Background. Если вам нужно дополнительное содержимое поверх рисунка, вы можете объединить их с Gridобъектом верхнего уровня в содержимом.

Однако, если вы буквально просто хотите полностью отключить эффект наведения (а не просто скрыть его), вы можете использовать конструктор XAML Visual Studio:

  1. При редактировании XAML выберите вкладку «Дизайн» .
  2. На вкладке «Дизайн» найдите кнопку, для которой вы хотите отключить эффект.
  3. Щелкните эту кнопку правой кнопкой мыши и выберите «Редактировать шаблон / Редактировать копию ...» . Выберите в приглашении, где вы хотите разместить новый ресурс шаблона. Будет казаться, что это ничего не делает, но на самом деле дизайнер добавит новые ресурсы туда, где вы ему сказали, и изменит ваш элемент кнопки, чтобы он ссылался на стиль, который использует эти ресурсы в качестве шаблона кнопки.
  4. Теперь вы можете редактировать этот стиль. Самый простой способ - удалить или закомментировать (например, Ctrl+ E, C) <Trigger Property="IsMouseOver" Value="true">...</Trigger>элемент. Конечно, на этом этапе вы можете внести в шаблон любые изменения.

Когда вы закончите, стиль кнопки будет выглядеть примерно так:

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

(Примечание: вы можете опустить p:квалификацию пространства имен XML в фактическом коде ... Я привожу их здесь только потому, что средство форматирования кода XML Stack Overflow запутывается <Style/>элементами, у которых нет полного имени с пространством имен XML.)

Если вы хотите применить тот же стиль к другим кнопкам, вы можете просто щелкнуть их правой кнопкой мыши, выбрать «Редактировать шаблон / Применить ресурс» и выбрать стиль, который вы только что добавили для первой кнопки. Вы даже можете сделать этот стиль стилем по умолчанию для всех кнопок, используя обычные методы применения стиля по умолчанию к элементам в XAML.

Питер Дунихо
источник
6
Спасибо. Это единственный приемлемый ответ здесь
Джаред Бич
13

У меня это сработало.

Стиль кнопки

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

Кнопка

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

Примечания

  • На кнопке отображается маленький синий крестик, очень похожий на тот, который используется для закрытия окна.
  • Устанавливая фон сетки на «Прозрачный», он добавляет проверку, что означает, что если мышь находится где-нибудь над кнопкой, она будет работать. Опустите этот тег, и кнопка загорится, только если указатель мыши находится над одной из векторных линий значка (это не очень удобно).
Контанго
источник
1
Это отличный ответ, но как насчет изменения Strokeцвета при наведении курсора, Borderа не только на Path?
Nateous
1
Эта x:Key="TransparentStyle"часть и ее использование были важны для меня ... Спасибо!
nrod
6

Просто хочу поделиться своим стилем кнопок из моего ResourceDictionary, который я использовал. Вы можете свободно изменять фон onHover в триггерах стиля. « ColorAnimation To = * желаемый BG (например, # FFCEF7A0)». Кнопка BG также автоматически вернется к своей исходной BG после состояния mouseOver. Вы даже можете установить скорость перехода.

Словарь ресурсов

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

все, что вам нужно сделать, это назвать стиль.

Пример реализации

<Button Style="{StaticResource Flat_Button}" Height="Auto"Width="Auto">  
     <StackPanel>
     <TextBlock Text="SAVE" FontFamily="Arial" FontSize="10.667"/>
     </StackPanel>
</Button>
Джастин Адриас
источник
3

Немного более сложный ответ, который использует ControlTemplate и имеет эффект анимации (адаптировано из https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/customizing-the-appearance-of-an-existing- контроль )

В словаре ресурсов определите шаблон управления для вашей кнопки, например:

<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 вы можете использовать шаблон выше для своей кнопки, как показано ниже:

Определите свою кнопку

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

Надеюсь, это поможет

Якобос Каракизас
источник
0

Для изменения стиля кнопки

1-й: определение стилей ресурсов

<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-й определить код кнопки

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

3-й код позади

    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;

        }
    }
Анхель Ибаньес
источник