Làm cách nào để thay đổi Nền cho Nút MouseOver trong WPF?


93

Tôi có một nút trên trang của mình với XAML này:

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

Nhưng khi tôi đưa chuột lên nút của mình, nền của nút sẽ thay đổi thành nền xám của cửa sổ mặc định.
Vấn đề là gì?

Đây là hình ảnh nút trước và sau khi di chuột qua:
Trước:
Trước
Sau:
Sau


Nhưng bạn phải khởi động hình ảnh Forward-48.pngvà kích hoạt IsMouseOver để thay đổi nó cho giống nhau Forward-48.png. Tôi đang thử sử dụng mã của bạn với các hình ảnh khác nhau và tất cả đều hoạt động tốt.
Anatoliy Nikolaev

1
@anatoliy: Nó không hoạt động.
Sepehr Mohammadi

Sau khi là màu mặc định của bạn? Bất kỳ nơi nào khác bạn không thay đổi / không đặt nền nút? Tôi có mã của bạn hoạt động tốt.
Anatoliy Nikolaev

Câu trả lời:


173

Để loại bỏ MouseOverhành vi mặc định trên, Buttonbạn sẽ cần phải sửa đổi ControlTemplate. Thay đổi Styleđịnh nghĩa của bạn thành như sau sẽ thực hiện thủ thuật:

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

CHỈNH SỬA: Đã muộn vài năm, nhưng bạn thực sự có thể đặt bút vẽ đường viền bên trong đường viền ở đó. Không, nếu điều đó đã được chỉ ra nhưng có vẻ như nó không phải là ...


1
Điều này hoạt động, tuy nhiên nút Biên giới sẽ biến mất! Phải đặt một phần tử <Border BorderBrush = "DarkGray" BorderThickness = "1"> xung quanh nút.
Venugopal M

4
@CF lý do cho điều này là kiểu Nút tiêu chuẩn có các trình kích hoạt bên trong ControlTemplate, vì vậy chúng ghi đè các Styletrình kích hoạt của OP .
torvin

1
@torvin Điều đó có vẻ ngược quá! Tại sao một trình kích hoạt do người dùng xác định phải được ghi đè bởi những trình kích hoạt mặc định? Tôi hiểu cấu trúc phân cấp, ControlTemplate nằm trên Style, nhưng tôi không hiểu tại sao việc ghi đè các cài đặt cơ bản như thế này lại rất khó khăn.
Fuselight

@Fuselight, trình kích hoạt bên trong ControlTemplatevề cơ bản cho biết 'Sơn viền phù hợp với Backgroundmàu sắc. Và nếu chuột ở trên nút - hãy sơn đường viền đó bằng màu này thay thế ', trong khi ở kiểu bạn chỉ có quyền truy cập vào Backgroundmàu chứ không phải màu đường viền bên dưới. Tôi thấy bạn chỉ dù, WPF phong lá nhiều để được mong muốn ...
torvin

Điều này có thêm lợi ích là loại bỏ hộp màu xanh lam hiển thị khi cuộn qua, khi sử dụng hình ảnh có nền trong suốt. Trong trường hợp của tôi, tôi không muốn biên giới, vì vậy bộ BorderThickness đến 0.
Chuck Savage

20

Tất cả các câu trả lời cho đến nay đều liên quan đến việc thay thế hoàn toàn hành vi của nút mặc định bằng một thứ khác. Tuy nhiên, IMHO sẽ hữu ích và quan trọng khi hiểu rằng bạn có thể chỉ thay đổi phần mà bạn quan tâm , bằng cách chỉnh sửa mẫu mặc định hiện có cho phần tử XAML.

Trong trường hợp xử lý hiệu ứng di chuột trên nút WPF, sự thay đổi về diện mạo trong Buttonphần tử WPF là do Triggerkiểu mặc định cho phần tử Buttonnày dựa trên thuộc IsMouseOvertính và đặt các thuộc tính BackgroundBorderBrushcủa Borderphần tử cấp cao nhất trong mẫu điều khiển. Nền của Buttonphần tử nằm bên dưới Bordernền của phần tử, vì vậy việc thay đổi thuộc Button.Backgroundtính không ngăn hiệu ứng di chuột được nhìn thấy.

Với một số nỗ lực, bạn có thể ghi đè hành vi này bằng bộ cài đặt của riêng mình, nhưng vì phần tử bạn cần ảnh hưởng nằm trong mẫu và không thể truy cập trực tiếp trong XAML của riêng bạn, nên cách tiếp cận đó sẽ khó và IMHO quá phức tạp.

Một tùy chọn khác sẽ là sử dụng đồ họa làm Contentcho Buttonthay vì Background. Nếu bạn cần nội dung bổ sung trên hình ảnh, bạn có thể kết hợp chúng với một Gridđối tượng cấp cao nhất trong nội dung.

Tuy nhiên, nếu bạn thực sự chỉ muốn tắt hoàn toàn hiệu ứng di chuột (thay vì chỉ ẩn nó), bạn có thể sử dụng Visual Studio XAML Designer:

  1. Trong khi chỉnh sửa XAML của bạn, hãy chọn tab "Thiết kế" .
  2. Trong tab "Thiết kế" , tìm nút mà bạn muốn tắt hiệu ứng.
  3. Nhấp chuột phải vào nút đó và chọn "Chỉnh sửa Mẫu / Chỉnh sửa Bản sao ..." . Chọn trong lời nhắc bạn nhận được nơi bạn muốn đặt tài nguyên mẫu mới. Điều này có vẻ như không làm gì cả, nhưng trên thực tế, Nhà thiết kế sẽ thêm tài nguyên mới mà bạn đã nói với nó và thay đổi phần tử nút của bạn để tham chiếu kiểu sử dụng các tài nguyên đó làm mẫu nút.
  4. Bây giờ, bạn có thể chỉnh sửa kiểu đó. Điều dễ dàng nhất là xóa hoặc bỏ nhận xét (ví dụ: Ctrl+ E, C) <Trigger Property="IsMouseOver" Value="true">...</Trigger>phần tử. Tất nhiên, bạn có thể thực hiện bất kỳ thay đổi nào đối với mẫu bạn muốn tại thời điểm đó.

Khi bạn hoàn tất, kiểu nút sẽ giống như sau:

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

(Lưu ý: bạn có thể bỏ qua các p:điều kiện của vùng tên XML trong mã thực… Tôi chỉ cung cấp chúng ở đây vì trình định dạng mã Stack Overflow XML bị nhầm lẫn bởi <Style/>các phần tử không có tên đủ điều kiện với vùng tên XML.)

Nếu bạn muốn áp dụng cùng một kiểu cho các nút khác, bạn có thể nhấp chuột phải vào chúng và chọn "Chỉnh sửa Mẫu / Áp dụng Tài nguyên" và chọn kiểu bạn vừa thêm cho nút đầu tiên. Bạn thậm chí có thể đặt kiểu đó làm kiểu mặc định cho tất cả các nút, sử dụng các kỹ thuật thông thường để áp dụng kiểu mặc định cho các phần tử trong XAML.


5
Cám ơn rất nhiều. Đây là câu trả lời duy nhất có thể chấp nhận được ở đây
Jared Beach

13

Điều này làm việc tốt cho tôi.

Kiểu nút

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

Cái nút

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

Ghi chú

  • Nút hiển thị một dấu thập nhỏ màu xanh lam, giống như nút được sử dụng để đóng cửa sổ.
  • Bằng cách đặt nền của lưới thành "Trong suốt", nó sẽ thêm phần cao nhất, có nghĩa là nếu chuột ở bất kỳ đâu trên nút thì nó sẽ hoạt động. Bỏ qua thẻ này và nút sẽ chỉ sáng lên nếu chuột ở trên một trong các đường vectơ trong biểu tượng (điều này không thể sử dụng được).

1
Đây là một câu trả lời tuyệt vời, nhưng còn việc thay đổi Strokemàu sắc khi di chuột của Bordernó, nếu không có nó chỉ di chuột qua Path?
Nateous

1
Phần này x:Key="TransparentStyle"và cách sử dụng rất quan trọng để tôi đạt được điều đó ... Cảm ơn!
nrod

6

Chỉ muốn chia sẻ kiểu nút của tôi từ ResourceDictionary mà tôi đang sử dụng. Bạn có thể tự do thay đổi nền onHover tại trình kích hoạt kiểu. " ColorAnimation To = * BG mong muốn của bạn (tức là # FFCEF7A0)". Nút BG cũng sẽ tự động hoàn nguyên về BG ban đầu sau trạng thái mouseOver. Bạn thậm chí có thể đặt tốc độ chuyển đổi.

Từ điển tài nguyên

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

tất cả những gì bạn phải làm là gọi kiểu dáng.

Triển khai ví dụ

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

2

Một câu trả lời khó hơn một chút sử dụng ControlTemplate và có hiệu ứng hoạt ảnh (phỏng theo https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/customizing-the-appearance-of-an-existing- kiểm soát )

Trong từ điển tài nguyên của bạn, hãy xác định một mẫu điều khiển cho nút của bạn như sau:

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

trong XAML của bạn, bạn có thể sử dụng mẫu ở trên cho nút của mình như sau:

Xác định nút của bạn

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

Hy vọng nó giúp


0

Để thay đổi kiểu nút

Thứ nhất: xác định kiểu tài nguyê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>

Mã nút xác định thứ hai

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

Mã thứ 3 phía sau

    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;

        }
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.