I want to grey out my images (on the buttons) when the buttons are disabled. When I have text (no images) on the button, the text is greyed out (With Images as Button Content they are not grey out). Is there any simple and beautiful way to do that?
This is my xaml file:
<Window x:Class="WpfApplication2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*"/> </Grid.RowDefinitions> <ToolBarTray VerticalAlignment="Top" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" IsLocked="true" Grid.Row="0"> <ToolBar Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Band="1" BandIndex="1"> <Button Command="{Binding Button1}" RenderOptions.BitmapScalingMode="NearestNeighbor"> <Button.Content> <Image Source="open.ico"></Image> </Button.Content> </Button> <Button Command="{Binding Button2}" RenderOptions.BitmapScalingMode="NearestNeighbor"> <Button.Content> <Image Source="open.ico"></Image> </Button.Content> </Button> </ToolBar> </ToolBarTray> </Grid> </Window>
and this is my code behind file:
public partial class MainWindow : Window { private RelayCommand _button1; private RelayCommand _button2; public MainWindow() { InitializeComponent(); DataContext = this; } public ICommand Button1 { get { if (_button1 == null) { _button1 = new RelayCommand(Button1E, Button1C); } return _button1; } } public ICommand Button2 { get { if (_button2 == null) { _button2 = new RelayCommand(Button2E, Button2C); } return _button2; } } public void Button1E(object parameter) { Trace.WriteLine("Button 1"); } public bool Button1C(object parameter) { return true; } public void Button2E(object parameter) { Trace.WriteLine("Button 2"); } public bool Button2C(object parameter) { return false; } }
You should put your CSS styles into a stylesheet rather than directly onto the HTML . Once it's set as a CSS style rule you can then use the :disabled flag to set styles for when that attribute is true. You can not use the :disabled flag on inline styles.
Going from gray to fully colored is an unpredictable change that can affect user expectations. For a smooth and seamless experience, it's best to avoid graying out your disabled buttons. Instead, you should decrease the opacity to make it transparent.
As Thomas Lebrun says in his post How to gray the icon of a MenuItem ? the best way at the moment is probably to create a little class, AutoGreyableImage, which allow you to have an image that will be turn in gray automatically when the control is deactivated.
Here is how you can use it:
<MenuItem Header="Edit"> <MenuItem x:Name="miPaste" Header="Paste"> <MenuItem.Icon> <local:AutoGreyableImage Source="pack://application:,,,/Images/Paste.png" /> </MenuItem.Icon> </MenuItem> </MenuItem>
And here is the implementation:
/// <summary> /// Class used to have an image that is able to be gray when the control is not enabled. /// Author: Thomas LEBRUN (http://blogs.developpeur.org/tom) /// </summary> public class AutoGreyableImage : Image { /// <summary> /// Initializes a new instance of the <see cref="AutoGreyableImage"/> class. /// </summary> static AutoGreyableImage() { // Override the metadata of the IsEnabled property. IsEnabledProperty.OverrideMetadata(typeof(AutoGreyableImage), new FrameworkPropertyMetadata(true, new PropertyChangedCallback(OnAutoGreyScaleImageIsEnabledPropertyChanged))); } /// <summary> /// Called when [auto grey scale image is enabled property changed]. /// </summary> /// <param name="source">The source.</param> /// <param name="args">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> private static void OnAutoGreyScaleImageIsEnabledPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs args) { var autoGreyScaleImg = source as AutoGreyableImage; var isEnable = Convert.ToBoolean(args.NewValue); if (autoGreyScaleImg != null) { if (!isEnable) { // Get the source bitmap var bitmapImage = new BitmapImage(new Uri(autoGreyScaleImg.Source.ToString())); // Convert it to Gray autoGreyScaleImg.Source = new FormatConvertedBitmap(bitmapImage, PixelFormats.Gray32Float, null, 0); // Create Opacity Mask for greyscale image as FormatConvertedBitmap does not keep transparency info autoGreyScaleImg.OpacityMask = new ImageBrush(bitmapImage); } else { // Set the Source property to the original value. autoGreyScaleImg.Source = ((FormatConvertedBitmap) autoGreyScaleImg.Source).Source; // Reset the Opcity Mask autoGreyScaleImg.OpacityMask = null; } } } }
Here is the result:
Sources
You could use a pixel shader to do this automatically.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With