-2

This question is similar to others, but my research has not uncovered the answer I seek. I am trying to fill a rectangle with a brick pattern. I understand there is not a HatchBrush in WPF and if there was perhaps I would do this: HatchBrush brush = new HatchBrush(HatchStyle.DiagonalBrick,System.Drawing.Color.Black); But since there is not I am using a DrawingBrush as follows, which fills the rectangle with a darkblue solid color. Where do I specify the DiagonalBrick?

Rectangle fillRect = new Rectangle();
//Try to fill fillRect with a pattern
Rect aRect = new Rect();
aRect.Width = fillRect.Width;
aRect.Height = fillRect.Height;
GeometryGroup rectangle = new GeometryGroup();
GeometryDrawing geomDrawing = new GeometryDrawing(Brushes.DarkBlue,null, rectangle);
DrawingBrush drawingBrush = new DrawingBrush();
rectangle.Children.Add(new RectangleGeometry(aRect, 0, 0));
geomDrawing.Geometry = rectangle;
drawingBrush.Drawing = geomDrawing;
fillRect.Fill = drawingBrush;
J W
  • 71
  • 6
  • 1
    Why not use an image? – TheGeneral Feb 17 '20 at 21:26
  • 1
    Depending on your idea of how a brick pattern looks like, you would draw an appropriate set of lines, either as a single PathGeometry, or a collection of LineGeometries in a GeometryGroup. – Clemens Feb 17 '20 at 21:29
  • @MichaelRandall If you mean a raster image, that wouldn't be vector graphics, and wouldn't leverage the potential of WPF. – Clemens Feb 17 '20 at 21:31
  • @Clemens: Thanks, I think that's what I will have to do (unfortunately). I was looking for the "easy" solution. – J W Feb 17 '20 at 21:49
  • There are a number of similar, if not exact duplicates, on Stack Overflow already, i.e. people seeking to reproduce the GDI+ `HatchBrush` behavior in WPF. See marked duplicates. If after researching those and applying the solutions provided, you are still unable to get a solution to work, you will need to post a question that provides a good [mcve] that shows clearly what you've tried, and explain what _specifically_ it is you are still having trouble figuring out. – Peter Duniho Feb 17 '20 at 23:07

1 Answers1

1

There's actually quite a few different ways to do this, but based on the code you've posted I'll assume you want to create your own geometry, using pixels as your coordinate system, and use that to paint a rectangle. This is one of those cases where WPF's flexibility means you have to be a lot more verbose than you would in previous platforms, but let's work through it...

The brick pattern can be achieved by creating a DrawingBrush containing a GeometryDrawing. The trick is to create two bricks of size <60,40> that are offset:

enter image description here

The problem now is the black background poking through. We can solve that by placing a third brick to the left of the one on the bottom, and then setting the DrawBrush's Viewport and Viewbox to the rectangle <0,0,60,80>, and then setting TileMode to "Tile". The code to do this is as follows:

var brickBrush = new DrawingBrush
{
    Viewport = new Rect(0, 0, 60, 80),
    ViewportUnits = BrushMappingMode.Absolute,
    Viewbox = new Rect(0, 0, 60, 80),
    ViewboxUnits = BrushMappingMode.Absolute,
    TileMode = TileMode.Tile,
    Drawing = new GeometryDrawing
    {
        Brush = new SolidColorBrush(Color.FromRgb(0xB1, 0x78, 0x33)),
        Geometry = new GeometryGroup
        {
            Children = new GeometryCollection(new Geometry[] {
                new RectangleGeometry(new Rect( 0,   0, 60, 40)),
                new RectangleGeometry(new Rect( 30, 40, 60, 40)),
                new RectangleGeometry(new Rect(-30, 40, 60, 40))
            }),                     
        },
        Pen = new Pen(new SolidColorBrush(Color.FromRgb(0xE1, 0xD7, 0xBD)), 5)
    }
};

theRectangle.Fill = brickBrush;

Which will generate the following pattern:

enter image description here

As your WPF skill improves you'll eventually want to start doing stuff like this in XAML. For the purpose of comparison, here is the code needed to achieve the same fill:

<Window.Resources>

    <DrawingBrush x:Key="BrickBrush" Viewport="0,0,60,80" ViewportUnits="Absolute" Viewbox="0,0,60,80" ViewboxUnits="Absolute" TileMode="Tile">
        <DrawingBrush.Drawing>
            <GeometryDrawing Brush="#B17833">
                <GeometryDrawing.Geometry>
                    <GeometryGroup>
                        <RectangleGeometry Rect="0,0,60,40" />
                        <RectangleGeometry Rect="30,40,60,40" />
                        <RectangleGeometry Rect="-30,40,60,40" />
                    </GeometryGroup>
                </GeometryDrawing.Geometry>
                <GeometryDrawing.Pen>
                    <Pen Thickness="5" Brush="#E1D7BD" />
                </GeometryDrawing.Pen>
            </GeometryDrawing>
        </DrawingBrush.Drawing>
    </DrawingBrush>

</Window.Resources>

<Rectangle Fill="{StaticResource BrickBrush}" />

You've also alluded to wanting diagonal bricks, to do that you simply add a rotation transform to the DrawingBrush:

var brickBrush = new DrawingBrush
{
    Transform = new RotateTransform(45),
    ... etc ...

enter image description here

Mark Feldman
  • 15,731
  • 3
  • 31
  • 58
  • 1
    Thank you very much for your detailed and thoughtful response. You took the time to answer with greater detail than I expected, and furthermore encouraged me to discover a simpler way using XAML. I am grateful for your time and consideration. Once I successfully implement this I will click to accept your answer. – J W Feb 18 '20 at 03:41