A more complete version of AutoGreyableImage by Thomas Lebrun . For everyone who is interested, I started using the Thomas Lebruns class and ran into a few exceptions due to the null reference, and also found out that the image would not be disabled if the isEnabled property was set first and the source was set after.
So here is a class that finally helped. You can, of course, add an opacity question to this, but I decided to leave it until xaml around the image.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media.Imaging; using System.Windows.Media; namespace MyDisabledImages { /// <summary> /// Class used to have an image that is able to be gray when the control is not enabled. /// Based on the version by 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 and Source property. IsEnabledProperty.OverrideMetadata(typeof(AutoGreyableImage), new FrameworkPropertyMetadata(true, new PropertyChangedCallback(OnAutoGreyScaleImageIsEnabledPropertyChanged))); SourceProperty.OverrideMetadata(typeof(AutoGreyableImage), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnAutoGreyScaleImageSourcePropertyChanged))); } protected static AutoGreyableImage GetImageWithSource(DependencyObject source) { var image = source as AutoGreyableImage; if (image == null) return null; if (image.Source == null) return null; return image; } /// <summary> /// Called when [auto grey scale image source property changed]. /// </summary> /// <param name="source">The source.</param> /// <param name="args">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> protected static void OnAutoGreyScaleImageSourcePropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs ars) { AutoGreyableImage image = GetImageWithSource(source); if (image != null) ApplyGreyScaleImage(image, image.IsEnabled); } /// <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> protected static void OnAutoGreyScaleImageIsEnabledPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs args) { AutoGreyableImage image = GetImageWithSource(source); if (image != null) { var isEnabled = Convert.ToBoolean(args.NewValue); ApplyGreyScaleImage(image, isEnabled); } } protected static void ApplyGreyScaleImage(AutoGreyableImage autoGreyScaleImg, Boolean isEnabled) { try { if (!isEnabled) { BitmapSource bitmapImage = null; if (autoGreyScaleImg.Source is FormatConvertedBitmap) { // Already grey ! return; } else if (autoGreyScaleImg.Source is BitmapSource) { bitmapImage = (BitmapSource)autoGreyScaleImg.Source; } else // trying string { bitmapImage = new BitmapImage(new Uri(autoGreyScaleImg.Source.ToString())); } FormatConvertedBitmap conv = new FormatConvertedBitmap(bitmapImage, PixelFormats.Gray32Float, null, 0); autoGreyScaleImg.Source = conv; // Create Opacity Mask for greyscale image as FormatConvertedBitmap does not keep transparency info autoGreyScaleImg.OpacityMask = new ImageBrush(((FormatConvertedBitmap)autoGreyScaleImg.Source).Source); //equivalent to new ImageBrush(bitmapImage) } else { if (autoGreyScaleImg.Source is FormatConvertedBitmap) { autoGreyScaleImg.Source = ((FormatConvertedBitmap)autoGreyScaleImg.Source).Source; } else if (autoGreyScaleImg.Source is BitmapSource) { // Should be full color already. return; } // Reset the Opcity Mask autoGreyScaleImg.OpacityMask = null; } } catch (Exception) { // nothin' } } } }
source share