How to make WPF image disabled?

I need an image that is disabled when disabled (IsEnabled = False). A grayish version of the image can be obtained by reading BitmapImage in the FormatConvertedBitmap format, which is displayed here .

I managed to get this working with UserControl, but now I would like to have the same behavior in the specialized Image class for more flexibility. I don't care if this is implemented in XAML, in code, or both, but it should be a subclass of Image.

Use may be:

<DisableableImage Source="Images/image1.png" /> <DisableableImage Source="Images/image1.png" IsEnabled="False" /> <!-- Since IsEnabled is inherited down the tree, the image will be grayed out like the rest of the button --> <Button IsEnabled="False"> <StackPanel Orientation="Horizontal"> <TextBlock>OK</TextBlock> <DisableableImage Source="Images/ok.png" /> </StackPanel> </Button> 
+3
source share
5 answers

Check out this link

EDIT: Or this one (all you need is an AutoGreyableImage class)

+9
source

I made a small comparison based on the following solutions.

Since I already had licensing for Infragistics Net Advantage for WPF, it was easy to try it

Here is the result

enter image description here

Therefore, the best approach depends on what results you have after. For me, I think the result expressed by> AutoDisabledImage is too bright, AutoGreyableImage does a pretty good job (Identical result for approach 1 (OP link)) and GreyscaleEffect gives a better result.

+5
source

if you use this a lot, consider creating a custom effect introduced with .NET 3.5 SP1 (not bitmapeffect) to do this on your GPU. this effect can be easily controlled using triggers.

+2
source

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' } } } } 
+2
source

Create the DisableableImage class, which is a typical WPF control. Inside, place two elements: an image and a rectangle that appears only when the control is disabled. The rectangle must have the same width and height as the image, and must overlap the image. If the color of gray and alpha is about 40%, you should get an effect similar to the actual section of the image - without any effort to actually change the image.

0
source

Source: https://habr.com/ru/post/1415174/


All Articles