You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF:不修改已有Button样式实现点击切换图标可见性

解决Button点击切换图标颜色(不修改全局样式)

一、基于现有双图标的快速解决方案

全局样式无法访问Button内部的Image元素(作用域限制),直接把触发逻辑移到Button内部即可,无需修改UserControl的资源样式:

修改Button的XAML,给内部StackPanel添加绑定Button状态的触发器:

<Button Command="{Binding NavigateCommand}" CommandParameter="CalibrationMain">
    <StackPanel>
        <Image Name="ImageDefault"
               Source="pack://application:,,,/Images;component/Icons/UnknownSize/CalibrationIconWhite.png"
               Width="100" Height="100"/>
        <Image Name="ImageOnClick"
               Source="pack://application:,,,/Images;component/Icons/UnknownSize/CalibrationIconBlack.png"
               Width="100" Height="100" Visibility="Collapsed"/>
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Top" Text="Calibration" FontSize="18"/>
        
        <!-- 内部触发器,绑定Button的IsPressed状态 -->
        <StackPanel.Triggers>
            <DataTrigger Binding="{Binding IsPressed, RelativeSource={RelativeSource AncestorType=Button}}" Value="True">
                <Setter TargetName="ImageDefault" Property="Visibility" Value="Collapsed"/>
                <Setter TargetName="ImageOnClick" Property="Visibility" Value="Visible"/>
            </DataTrigger>
        </StackPanel.Triggers>
    </StackPanel>
</Button>

二、更高效的单图标方案(无需双图)

双图方案冗余且不优雅,推荐用颜色转换实现单图标动态变色,节省资源:

方法1:绑定+转换器动态修改图标颜色

准备一张基准色图标(比如白色),通过转换器在Button按下时替换颜色:

  1. 编写颜色转换转换器:
public class ImageColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool isPressed = (bool)value;
        BitmapImage originalImage = new BitmapImage(new Uri("pack://application:,,,/Images;component/Icons/UnknownSize/CalibrationIconWhite.png"));
        
        FormatConvertedBitmap convertedBitmap = new FormatConvertedBitmap();
        convertedBitmap.BeginInit();
        convertedBitmap.Source = originalImage;
        convertedBitmap.DestinationFormat = PixelFormats.Bgra32;
        convertedBitmap.EndInit();

        int stride = convertedBitmap.PixelWidth * 4;
        byte[] pixels = new byte[stride * convertedBitmap.PixelHeight];
        convertedBitmap.CopyPixels(pixels, stride, 0);

        for (int i = 0; i < pixels.Length; i += 4)
        {
            if (pixels[i + 3] > 0)
            {
                if (isPressed)
                {
                    pixels[i] = 0; pixels[i + 1] = 0; pixels[i + 2] = 0;
                }
                else
                {
                    pixels[i] = 255; pixels[i + 1] = 255; pixels[i + 2] = 255;
                }
            }
        }

        WriteableBitmap writeableBitmap = new WriteableBitmap(convertedBitmap.PixelWidth, convertedBitmap.PixelHeight, 96, 96, PixelFormats.Bgra32, null);
        writeableBitmap.WritePixels(new Int32Rect(0, 0, convertedBitmap.PixelWidth, convertedBitmap.PixelHeight), pixels, stride, 0);
        return writeableBitmap;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
  1. 在UserControl资源中声明转换器(保留原有Button样式不变):
<UserControl.Resources>
    <local:ImageColorConverter x:Key="ImageColorConverter"/>
    <Style TargetType="{x:Type Button}" BasedOn="{StaticResource ButtonStyle}">
        <Setter Property="Margin" Value="10"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="Cursor" Value="Hand"/>
        <Style.Resources>
            <Style TargetType="Rectangle">
                <Setter Property="RadiusX" Value="8"/>
                <Setter Property="RadiusY" Value="8"/>
            </Style>
        </Style.Resources>
    </Style>
</UserControl.Resources>
  1. 修改Button的Image绑定:
<Button Command="{Binding NavigateCommand}" CommandParameter="CalibrationMain">
    <StackPanel>
        <Image Width="100" Height="100"
               Source="{Binding IsPressed, RelativeSource={RelativeSource AncestorType=Button}, Converter={StaticResource ImageColorConverter}}"/>
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Top" Text="Calibration" FontSize="18"/>
    </StackPanel>
</Button>

方法2:VisualBrush+Rectangle(适合矢量图标)

如果图标是矢量形状,直接用VisualBrush定义图标,通过改变Rectangle填充色实现切换:

<Button Command="{Binding NavigateCommand}" CommandParameter="CalibrationMain">
    <StackPanel>
        <Rectangle Width="100" Height="100">
            <Rectangle.Fill>
                <VisualBrush>
                    <VisualBrush.Visual>
                        <!-- 替换为你的矢量图标路径 -->
                        <Path Data="M10,10 L50,10 L50,50 L10,50 Z" Fill="White" />
                    </VisualBrush.Visual>
                </VisualBrush>
            </Rectangle.Fill>
            
            <Rectangle.Style>
                <Style TargetType="Rectangle">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsPressed, RelativeSource={RelativeSource AncestorType=Button}}" Value="True">
                            <Setter Property="Fill">
                                <Setter.Value>
                                    <VisualBrush>
                                        <VisualBrush.Visual>
                                            <Path Data="M10,10 L50,10 L50,50 L10,50 Z" Fill="Black" />
                                        </VisualBrush.Visual>
                                    </VisualBrush>
                                </Setter.Value>
                            </Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Rectangle.Style>
        </Rectangle>
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Top" Text="Calibration" FontSize="18"/>
    </StackPanel>
</Button>

内容的提问来源于stack exchange,提问作者OrionsBelt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 05:01:00