WPF:不修改已有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按下时替换颜色:
- 编写颜色转换转换器:
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(); } }
- 在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>
- 修改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
相关产品推荐
相关产品推荐

