Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Move Thumb with Rainbow Grid Adorner.

0.00/5 (No votes)
8 Jul 2014 1  
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

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

    AdornerLayer _layer;
        CanvasAdorner _adorner;

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

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.

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.

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.

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

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.

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here