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

Move Thumb with Rainbow Grid Adorner.

Rate me:
Please Sign up or sign in to vote.
4.83/5 (6 votes)
8 Jul 2014CPOL2 min read 12.7K   8  
I made Adorner which displayed Rainbow color Grid in Canvas.

Introduction

Last year I joined a WPF project. And there I experienced many problems. One problem is that I made a UserControl that can move in a Grid Control, but it couldn't resize himself in the Grid Control. This was because the Resizing Control couldn't go over the boundary of the Grid Cells. After all, I implemented moving functions only. The resize function can't be implemented.

Until now. I have been thinking how to resize the control in a grid. Here is one solution I tried.

This is not Grid control, this is Adorner(Fake Grid). However, you could add some features (resize element etc.) to it, if you wanted to resize elements.

Background

You make the Adorner Element From Canvas. If you started dragging, then the fake grid adorner is shown up. And if you stop dragging, it is shown down.

Grid(Fake Grid) is a large composition of many geometries.

Grid's color is Rainbow Color because I want to show that you can change grid color anyway.

How to make this.

1. This is MainWindow.xaml below

XML
<Canvas Name="_canvas" Background="White" Width="500" Height="300">
    <Thumb DragStarted="Thumb_DragStarted"
               DragDelta="Thumb_DragDelta"
               DragCompleted="Thumb_DragCompleted" Canvas.Left="112" Canvas.Top="50">
        <Thumb.Template>
                <ControlTemplate>
                    <!-- In ControlTemplate, Define Object to move. -->
                    <Grid Width="150" Height="150">
                        <Ellipse Fill="Blue" Stroke="LightBlue"
                                 Width="{TemplateBinding Width}"
                                 Height="{TemplateBinding Height}"
                        />
                    </Grid>
        </ControlTemplate>
            </Thumb.Template>
        </Thumb>
</Canvas>

First, we replace grid to canvas in the Window tag, or place canvas in the grid tag. On Canvas we place one Thumb there. All Thumb Controls have one Template property. We set this property the ControlTemplate as shown below. This ControlTemplate has an Ellipse in a Grid . It decides the look at the Thumb itself. Finally, we add three events to that Thumb Control.

2. We use Adorner to show the grid, then add AdornerLayer and Adorner fields to the MainWindow.xaml.cs file.

C#
AdornerLayer _layer;
    CanvasAdorner _adorner;

3. Next we make three EventHandlers of Thumb Control and write it.

C#
private void Thumb_DragStarted(object sender, DragStartedEventArgs e)
{
     _layer = AdornerLayer.GetAdornerLayer(_canvas);
     _adorner = new CanvasAdorner(_canvas);

     Path _backGrid = MakeStreamGeometry(_canvas, new Size(100, 100));
     Canvas.SetTop(_backGrid, 0);
     Canvas.SetLeft(_backGrid, 0);

     _adorner.AddAdornment(_backGrid);
     _layer.Add(_adorner);
}

private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
{
     var thumb = sender as Thumb;
     if (thumb == null) return;

     // Thumb control moves according to quantity of drug.
     Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange);
     Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange);
}

private void Thumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
     var layer = AdornerLayer.GetAdornerLayer(_canvas);
     _layer.Remove(_adorner);
}

The first method starts on Mouse down. This is to get Canvas 's AdornerLayer. And the next line is to get Canvas's AdornerControl to add that layer. The third line is a Method, MakeStreamGeometry(), that gets Fake Grid GeometryObjects, and set it to the Canvas's AdornerLayer with AdornerElement. (Size 100 means Fake Grid's Cell Width and Height)

The second Method means Thumb Moving.

The third Method occurs on Mouse up and gets to AdornerLayer again and delete it.

4. Next Method is to initialize drawing objects.

C#
private Path MakeStreamGeometry(Canvas _canvas, Size _cellSize)
{
     Brush myBrush = MakeRainbowBrush();
     Path myPath = new Path()
     {
                Stroke = myBrush,
                StrokeThickness = 3.0,
                StrokeDashOffset = 1.5,
                Opacity = 0.95,
                StrokeDashArray = { 5.0, 2.5 },
     };
        
     var geometry = new StreamGeometry();

     using (var ctx = geometry.Open())
     {
           DrawGridLines(_canvas, _cellSize, ctx);
     }                 

     myPath.Data = geometry;

     return myPath;
}

It sets Brush and Path first. myPath is Shape instance that means the Shape of Grid. That is initialized and set by geometry object at Data property. DrawGridLines Method is make geometry drawings.

5. This Method calculates point for drawing grid. and calculates number of Rows, Columns.

C#
private static Point DrawGridLines(Canvas _canvas, Size _size, StreamGeometryContext ctx)
{
      Point _pointOffset = new Point(0, 0);

      int rowCount = (int)System.Math.Floor(_canvas.ActualHeight / _size.Height);
      int colCount = (int)System.Math.Floor(_canvas.ActualWidth / _size.Width);

      // Draw vertical lines.
      for (int i = 0; i < colCount + 1; i++)
      {
       ctx.BeginFigure(_pointOffset, true /* is filled */, false /* is closed */);
           _pointOffset.Y += _size.Height * rowCount;
           ctx.LineTo(_pointOffset, true /* is stroked */, false /* is smooth join */);

       _pointOffset.Y = 0;
           _pointOffset.X += _size.Width;
      }

      // Draw horizonal lines.
      for (int i = 0; i < rowCount + 1; i++)
      {
           ctx.BeginFigure(_pointOffset, true , false);
       _pointOffset.X += _size.Width * (colCount);
           ctx.LineTo(_pointOffset, true, false);
           
       _pointOffset.X = 0;
           _pointOffset.Y += _size.Height;
      }
    
      return _pointOffset;
}

using GeometryContext, it draws "L" like lines many times and two lines finally, because repeating Rectangles caused a Line on Line problem. Therefore, I do it this way.

Image 1

6. It is the Method to make Brush using by LinearGradientBrush Class.

C#
private static Brush MakeRainbowBrush()
{
     // Rainbow...Red,Orange,Yellow,Green,Blue,Violet
     LinearGradientBrush rainbowBrush = new LinearGradientBrush()
     {
          StartPoint = new Point(0, 0),
          EndPoint = new Point(1, 1),
          GradientStops = new GradientStopCollection()
          {
            new GradientStop(Colors.Red, 0.16),
                new GradientStop(Colors.Orange, 0.32),
                new GradientStop(Colors.Yellow, 0.48),
                new GradientStop(Colors.Green, 0.64),
                new GradientStop(Colors.Blue, 0.80),
                new GradientStop(Colors.Violet, 0.96),
                new GradientStop(Colors.Black, 1.0),
          },
     };

     return rainbowBrush;
}

This Method makes Rainbow Color Brush Object and returns to it.

This program is the result.

Image 2

Points of Interest

You can change the Grid any color. And move and resize elements.

History

7/7/2014 I posted it to CodeProject first time.

License

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


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

Comments and Discussions

 
-- There are no messages in this forum --