Bernhard 的个人资料Bernhard Grojer - Blog照片日志列表 工具 帮助

日志


10月8日

ADC 09 – Advanced DataBinding in WPF


Auf der ADC 09 habe ich einen Vortrag zum Thema DataBinding in  WPF gehalten.

Download: Beispiele & Präsentation auf Skydrive

Fragen zum Thema? Kommentar schreiben!

6月8日

WPF - ContextMenu via Code anzeigen


ctx.Placement = PlacementMode.Relative;
ctx.PlacementTarget = this;
ctx.PlacementRectangle = new Rect(30, 50, 0, 0);
ctx.IsOpen = true;


Sieht unschön aus und ist viel zu tippen. Lösung? Extension Methods aus .net 3.5.

ctx.Show(30, 50, this);

Besser?

Wie ist .Show definiert?

public static class Extensions
    {
        public static void Show(this ContextMenu ctx, double PositionX, double PositionY, UIElement relativeTo)
        {
            ctx.Placement = PlacementMode.Relative;
            ctx.PlacementTarget = relativeTo;
            ctx.PlacementRectangle = new Rect(PositionX, PositionY, 0, 0);
            ctx.IsOpen = true;
        }
    }

Download des Samples gibt es hier.

5月5日

Bitmaps in WPF (Transparenz-Angabe)


Nehmen wir mal an, wir haben ein Bitmap das wir in unserer Anwendung darstellen wollen.

Kein Problem in WPF:

<Image Source="img.bmp" />

TransparentWpfShoot2 

Doch der Magenta-Hintergrund ist nicht unbedingt das Ergebnis das wir erwartet haben. Transparenz muss also her.
Eine Möglichkeit wäre zu PNG oder dem GIF Format zu greifen. Alternativ hatten wir in WinForms die Option TransparentColor zu verwenden.

In WPF wird die Sache leider etwas mühsamer.

Wir können uns einen eigenen Converter für die Problemstellung schreiben:
public class BitmapTransparentConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            BitmapDecoder decoder = BitmapDecoder.Create(new Uri(value.ToString(), UriKind.Relative), BitmapCreateOptions.None, BitmapCacheOption.Default);

            BitmapSource sourceImage = decoder.Frames[0] as BitmapSource;
            Color transparentColor = Colors.Magenta; //Alternativ IMultiValueConverter und als Paramter verwenden

            sourceImage = new FormatConvertedBitmap(sourceImage, PixelFormats.Bgra32, null, 0.0);
            int step = (sourceImage.PixelWidth * sourceImage.Format.BitsPerPixel) / 8;
            byte[] pix = new byte[sourceImage.PixelHeight * step];
            sourceImage.CopyPixels(pix, step, 0);
            byte r = transparentColor.R;
            byte g = transparentColor.G;
            byte b = transparentColor.B;

            for (int i = 0; i < sourceImage.PixelHeight * step; i += (sourceImage.Format.BitsPerPixel / 8))
            {
                if (pix[i] == b && pix[i + 1] == g && pix[i + 2] == r)
                    pix[i + 3] = 0;
            }
            return BitmapSource.Create(sourceImage.PixelWidth, sourceImage.PixelHeight,
                                sourceImage.DpiX, sourceImage.DpiY, PixelFormats.Bgra32, sourceImage.Palette, pix, step);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

Danach noch einbinden in die Resourcen:

<Window.Resources>
        <local:BitmapTransparentConverter x:Key="BitmapConverter">           
        </local:BitmapTransparentConverter>
</Window.Resources>

und nun konsumieren:

<Image>
            <Image.Source>
                <Binding Converter="{StaticResource BitmapConverter}" Source="img.bmp" />
            </Image.Source>           
</Image>

TransparentWpfShoot1 

Aber Achtung. Performance ist nicht unbedingt optimal, wenn wir jedes mal (unnötig) konvertieren müssen um das Bild darzustellen.
Die KonverterKlasse kann dafür natürlich beliebig ausgebaut werden (Caching, ...)

Code zum Download