2012-07-03 1 views
19

Ich möchte meine Bilder (auf den Schaltflächen) ausgrauen, wenn die Schaltflächen deaktiviert sind. Wenn ich Text (keine Bilder) auf der Schaltfläche habe, ist der Text ausgegraut (Bei Bildern als Button-Inhalt sind sie nicht ausgegraut). Gibt es einen einfachen und schönen Weg, das zu tun?Bild auf der Schaltfläche ausgrauen, wenn das Element deaktiviert ist (einfache und schöne Weise)

Dies ist meine XAML-Datei:

<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> 

und dies ist mein Code hinter Datei:

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; 
    } 
} 
+1

Ich sehe keinen Versuch, das Problem im Code – Alex

Antwort

16

Wie Thomas Lebrun in seinem Beitrag How to gray the icon of a MenuItem ? sagt, ist der beste Weg im Moment wahrscheinlich, eine kleine Klasse zu erstellen, AutoGreableImage, die ein Bild ermöglicht, das automatisch grau wird, wenn das Steuerelement deaktiviert wird.

Hier ist, wie Sie es verwenden können:

<MenuItem Header="Edit"> 
    <MenuItem x:Name="miPaste" 
              Header="Paste"> 
        <MenuItem.Icon> 
            <local:AutoGreyableImage Source="pack://application:,,,/Images/Paste.png" 
                                                   /> 
        </MenuItem.Icon> 
    </MenuItem> 
</MenuItem> 
  

Und hier ist die Umsetzung:

/// <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; 
            } 
        } 
    } 
} 
  

Hier ist das Ergebnis:

Result of applying class to perform grayscale rendering when disabled

Sources

+0

Dead link? Ich habe mir die Mühe gemacht, mich beim Forum anzumelden und lächerliche Anti-Roboter-Fragen auf Französisch zu beantworten, und es zeigt sich, dass es eine leere Seite ist. Nicht fair! –

+0

@IvanKrivyakov Ich habe den toten Link zum Originalartikel aktualisiert. – David

+1

Das hat funktioniert. Merci! Danke für die schnelle Antwort. Es wäre aber nett, wenn du es anderen Leuten zugänglicher machen würdest, wie DropBox oder github.Die meisten WPF-Programmierer kennen kein Französisch und werden Schwierigkeiten haben, sich bei develop.net zu registrieren. –

4

Sie könnten use a pixel shader dies automatisch zu tun.

+0

anzugehen, nette, wusste ich nicht über diesen Effekt! Ich wünschte, ich hätte das vor 2 Jahren gelesen: p – David

3

Komplette Version des AutoGreableImage von Thomas Lebrun. Für alle Interessierten nutzte ich die Thomas Lebruns-Klasse und stieß dabei auf eine Reihe von NULLReference-Ausnahmen sowie darauf, dass ein Bild nicht deaktiviert würde, wenn die isEnabled-Eigenschaft zuerst festgelegt und die Quelle danach festgelegt wurde.

Also hier ist die Klasse, die endlich den Trick für mich gemacht hat. À propos, du kannst natürlich die Frage der Undurchsichtigkeit in dieses Thema einfügen, aber ich habe beschlossen, das dem Xaml um das Bild zu überlassen.

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' 
      } 

     } 

    } 
} 
3

Oder das gleiche von angehängten Eigenschaft.

<Image behaviors:GrayoutImageBehavior.GrayOutOnDisabled="True" Source="/WpfApp;component/Resources/picture.png" /> 

GrayoutImageBehavior:

public class GrayoutImageBehavior 
{ 
    public static readonly DependencyProperty GrayOutOnDisabledProperty = DependencyProperty.RegisterAttached("GrayOutOnDisabled", typeof(bool), typeof(GrayoutImageBehavior), new PropertyMetadata(default(bool), OnGrayOutOnDisabledChanged)); 
    public static void SetGrayOutOnDisabled(Image element, bool value) { element.SetValue(GrayOutOnDisabledProperty, value); } 
    public static bool GetGrayOutOnDisabled(Image element) { return (bool)element.GetValue(GrayOutOnDisabledProperty); } 

    private static void OnGrayOutOnDisabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) 
    { 
     Image image = (Image) obj; 
     image.IsEnabledChanged -= OnImageIsEnabledChanged; 

     if ((bool)args.NewValue) 
      image.IsEnabledChanged += OnImageIsEnabledChanged; 

     ToggleGrayOut(image); // initial call 
    } 

    private static void OnImageIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs args) 
    { 
     var image = (Image)sender; 
     ToggleGrayOut(image); 
    } 

    private static void ToggleGrayOut(Image image) 
    { 
     try 
     { 
      if (image.IsEnabled) 
      { 
       var grayImage = image.Source as FormatConvertedBitmap; 
       if (grayImage != null) 
       { 
        image.Source = grayImage.Source; // Set the Source property to the original value. 
        image.OpacityMask = null; // Reset the Opacity Mask 
        image.Opacity = 1.0; 
       } 
      } 
      else 
      { 
       var bitmapImage = default(BitmapImage); 

       if (image.Source is BitmapImage) 
        bitmapImage = (BitmapImage) image.Source; 
       else if (image.Source is BitmapSource) // assume uri source 
        bitmapImage = new BitmapImage(new Uri(image.Source.ToString())); 

       if (bitmapImage != null) 
       { 
        image.Source = new FormatConvertedBitmap(bitmapImage, PixelFormats.Gray32Float, null, 0); // Get the source bitmap 
        image.OpacityMask = new ImageBrush(bitmapImage); // Create Opacity Mask for grayscale image as FormatConvertedBitmap does not keep transparency info 
        image.Opacity = 0.3; // optional: lower opacity 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      LogicLogger.WriteLogEntry("Converting image to grayscale failed", LogLevel.Debug, false, ex); 
     } 
    } 
} 
1

I GrayoutImageBehavior geändert haben, so dass es nicht Speicherlecks aus dem Graubild sein, verursacht wird, wenn der Benutzer das Bild ändert ‚enable‘ Eigenschaft von true in false und umgekehrt mehrmals. Ich habe die DependencyProperty hinzugefügt, um das Graubild und die Graubild-Opazitätsmaske zu speichern.

public class GrayoutImageBehavior 
{ 
    public static readonly DependencyProperty GrayOutOnDisabledProperty = DependencyProperty.RegisterAttached("GrayOutOnDisabled", typeof(bool), typeof(GrayoutImageBehavior), new PropertyMetadata(default(bool), OnGrayOutOnDisabledChanged)); 
    public static void SetGrayOutOnDisabled(Image element, bool value) { element.SetValue(GrayOutOnDisabledProperty, value); } 
    public static bool GetGrayOutOnDisabled(Image element) { return (bool)element.GetValue(GrayOutOnDisabledProperty); } 

    private static DependencyProperty GrayImageProperty = DependencyProperty.RegisterAttached("GrayImage", typeof(FormatConvertedBitmap), typeof(GrayoutImageBehavior)); 
    private static void SetGrayImage(Image element, FormatConvertedBitmap value) { element.SetValue(GrayImageProperty, value); } 
    private static FormatConvertedBitmap GetGrayImage(Image element) { return (FormatConvertedBitmap)element.GetValue(GrayImageProperty); } 

    private static DependencyProperty GrayImageOpacityMaskProperty = DependencyProperty.RegisterAttached("GrayImageOpacityMask", typeof(Brush), typeof(GrayoutImageBehavior)); 
    private static void SetGrayImageOpacityMask(Image element, Brush value) { element.SetValue(GrayImageOpacityMaskProperty, value); } 
    private static Brush GetGrayImageOpacityMask(Image element) { return (Brush)element.GetValue(GrayImageOpacityMaskProperty); } 

    private static void OnGrayOutOnDisabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) 
    { 
     Image image = (Image)obj; 
     image.IsEnabledChanged -= OnImageIsEnabledChanged; 

     if ((bool)args.NewValue) 
      image.IsEnabledChanged += OnImageIsEnabledChanged; 

     ToggleGrayOut(image); // initial call 
    } 

    private static void OnImageIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs args) 
    { 
     var image = (Image)sender; 
     ToggleGrayOut(image); 
    } 

    private static void ToggleGrayOut(Image image) 
    { 
     try 
     { 
      if (image.IsEnabled) 
      { 
       var grayImage = image.Source as FormatConvertedBitmap; 
       if (grayImage != null) 
       { 
        image.Source = grayImage.Source; // Set the Source property to the original value. 
        image.OpacityMask = null; // Reset the Opacity Mask 
        //image.Opacity = 1.0; 
       } 
      } 
      else 
      { 
       FormatConvertedBitmap grayImage = GetGrayImage(image); 
       Brush grayOpacityMask = GetGrayImageOpacityMask(image); 

       if(grayImage == null) 
       { 
        var bitmapImage = default(BitmapImage); 

        if (image.Source is BitmapImage) 
         bitmapImage = (BitmapImage)image.Source; 
        else if (image.Source is BitmapSource) // assume uri source 
         bitmapImage = new BitmapImage(new Uri(image.Source.ToString())); 

        if (bitmapImage != null) 
        { 
         grayImage = new FormatConvertedBitmap(bitmapImage, PixelFormats.Gray32Float, null, 0); // Get the source bitmap 
         SetGrayImage(image, grayImage); 
         grayOpacityMask = new ImageBrush(bitmapImage); // Create Opacity Mask for grayscale image as FormatConvertedBitmap does not keep transparency info 
         SetGrayImageOpacityMask(image, grayOpacityMask); 
         //image.Opacity = 0.3; // optional: lower opacity 
        } 
       } 

       image.Source = grayImage; 
       image.OpacityMask = grayOpacityMask; 
      } 
     } 
     catch (Exception ex) 
     { 
      //LogicLogger.WriteLogEntry("Converting image to grayscale failed", LogLevel.Debug, false, ex); 
     } 
    } 
}