BilinearGradientBrushExtension, custom brush in WPF using MarkupExtension instead

来源:互联网 发布:网络受限制或无连接 编辑:程序博客网 时间:2024/04/29 15:41

WPF的类库现在锁死不让继承实现自定义的Brush,因为基类的brush含有抽象而且是internal的一些函数,像internal abstract System.Windows.Media.Composition.DUCE.ResourceHandle AddRefOnChannelCore(System.Windows.Media.Composition.DUCE.Channel channel),就没法继承实现,而且一般的DrawingBrush, ImageBrush都是sealed。而我这次需要一个相当于2维的GradientBrush一样的东西来实现传入一个颜色矩阵,画出一副ColorMap的东西。因为直接从brush继承设置想直接从imagesource继承都不可能,只好用MarkupExtension的方法绕:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows;
using System.Windows.Media.Animation;
using System.ComponentModel;


    [MarkupExtensionReturnType(
typeof(Brush))]
    
class BilinearGradientBrushExtension:MarkupExtension,INotifyPropertyChanged
    {
        List
<Color> colorMatrix = new List<Color>();
        
int countX, countY;

        
private void OnPropertyChanged(string propertyName)
        {
            
if (this.PropertyChanged != null)
            {
                
this.PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));
            }
        }

        
public List<Color> ColorMatrix
        {
            
get { return colorMatrix; }
            
set { colorMatrix = value ; OnPropertyChanged("ColorMatrix"); }
        }

        
public int CountY
        {
            
get { return countY; }
            
set { countY = value; }
        }

        
public int CountX
        {
            
get { return countX; }
            
set { countX = value; }
        }

        
public override object ProvideValue(IServiceProvider serviceProvider)
        {

            
int i = ColorMatrix.Count;

            
int[] pixelValues = GeneratePixelValues();

            WriteableBitmap bmp 
= new WriteableBitmap(countX, countY, 9696, PixelFormats.Pbgra32, null);
            bmp.WritePixels(
new Int32Rect(00, countX, countY), pixelValues, pixelValues.Length, 0);
            
            ImageBrush brush 
= new ImageBrush(bmp);

            
return brush;
        }

        
private int[] GeneratePixelValues()
        {
            
int pixelCount = countX * countY;

            
int[] pixelValues = new int[pixelCount];
            
for (int i = 0; i < countY; i++)
            {
                
for (int j = 0; j < countX; j++)
                {
                    Color c 
= ColorMatrix[i * countY + j];
                    
byte a = (byte)c.A;
                    
byte r = (byte)c.R;
                    
byte g = (byte)c.G;
                    
byte b = (byte)c.B;

                    pixelValues[i
*countY +j] = (a << 24+ (r << 16+ (g << 8+ b;
                }
            }
            
return pixelValues;
        }


        
#region INotifyPropertyChanged Members

        
public event PropertyChangedEventHandler PropertyChanged;

        
#endregion
    }

对应的xaml:

<l:BilinearGradientBrushExtension x:Name="contur" CountX="2" CountY="2">
       
<l:BilinearGradientBrushExtension.ColorMatrix>
                
<Color A="100" R="255" G="0" B="0" />
                
<Color A="100" R="0" G="255" B="0" />
                 
<Color A="100" R="155" G="155" B="155" />
                 
<Color A="100" R="0" G="0" B="255" />
        
</l:BilinearGradientBrushExtension.ColorMatrix>
</l:BilinearGradientBrushExtension>

 

产生的图片:

不过使用MarkupExtension的方法有个问题,就是产生的图像是静态的,颜色没办法在运行时改变,而且不能使用DependencyProperty,我试过INotifyProperty,会抛异常,暂时没有其他方法。