Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / WPF
Tip/Trick

Image that is grayed when disabled, for use in buttons, etc.

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
20 Mar 2011CPOL 22.1K   4   6
AutoGrayImage: An image class that changes to grayscale when it becomes disabled.
Download GrayImage.zip - 61.83 KB

Introduction


A well known WPF misfeature is that images of disabled (toolbar or other) buttons, or menuitems, are not displayed in grayscale. There are three well known ways around:

  • Set the image's Opacity with a trigger.
  • Set the image's Effect.
  • Use a custom image class.

All three approaches have been used before. Here I give an implementation of the third way.

Using the code

<Button>
  <my:AutoGrayImage Source2="/GrayImage;component/Images/Tulips.png" />
</Button>  

In the XAML, just replace your Image with AutoGrayImage, and set Source2 instead of the Source property. Here is how the result looks:




The Code


You should also add the following class to your project:
C#
public class AutoGrayImage : Image
{
    public AutoGrayImage()
    {
        IsEnabledChanged += new
      DependencyPropertyChangedEventHandler(AutoGrayImage_IsEnabledChanged);
    }

    void AutoGrayImage_IsEnabledChanged(object sender,
                            DependencyPropertyChangedEventArgs e)
    {
        Source = IsEnabled?Source2:GrayedImage;
    }
    FormatConvertedBitmap GrayedImage = null;

    public static readonly DependencyProperty Source2Property =
                 DependencyProperty.Register("Source2", typeof(BitmapSource),
                        typeof(AutoGrayImage), new PropertyMetadata(null,
                        OnSource2Changed));
    /// <summary>
    /// Sets the image to be grayed, or not.
    /// </summary>
    public BitmapSource Source2
    {
        get { return (BitmapSource)GetValue(Source2Property); }
        set { SetValue(Source2Property, value); }
    }
    static void OnSource2Changed(DependencyObject sender,
                                  DependencyPropertyChangedEventArgs e)
    {
        AutoGrayImage s = sender as AutoGrayImage;
        if (s.Source2 == null)
        {
            s.GrayedImage = null;
        }
        else
        {
            s.GrayedImage = new FormatConvertedBitmap(s.Source2,
                                PixelFormats.Gray8, null, 0);
            s.OpacityMask = new ImageBrush(s.Source2);
        }
        s.AutoGrayImage_IsEnabledChanged(s, new
                             DependencyPropertyChangedEventArgs());
    }
}

I admit that introducing another Source property, i.e., Source2, is not entirely clean. However, it seemed to be the option with the best (cleanliness / lines of code written) ratio.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralThank you :D Pin
LevanenG27-Jan-12 3:26
LevanenG27-Jan-12 3:26 
QuestionCurious... Pin
Andrew Rissing20-Mar-11 16:41
Andrew Rissing20-Mar-11 16:41 
AnswerRe: Curious... Pin
Thomas Willwacher20-Mar-11 17:26
Thomas Willwacher20-Mar-11 17:26 
GeneralRe: Curious... Pin
Andrew Rissing21-Mar-11 4:58
Andrew Rissing21-Mar-11 4:58 
GeneralNice Idea but... Pin
musters16-Mar-11 10:13
musters16-Mar-11 10:13 
GeneralRe: Nice Idea but... Pin
Thomas Willwacher16-Mar-11 11:04
Thomas Willwacher16-Mar-11 11:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.