none
Drawing a Rectangle in C# using WPF

    Question

  • I used a control to draw a rectangle, which is fine.  Is there a way to draw the same rectangle in C# without a control and place it at a particular row and column on the grid?  I know I can use XAML to do this, but what about straight C# code?  All the examples online don't seem to show a starting position for placement.  'Line' is not a control and so it can be drawn at a particular row and column.  What about a rectangle?  Rectangle doesn't seem to have any row and col fields like 'Line' does.

     

    Sutton

    Tuesday, August 17, 2010 6:37 PM

Answers

  • Does your grid have rows and columns? 

    If so this is wrong.  If not it isn't doing anything anyway.

     

    Comment this out:

      Grid.SetRow(ScheduleRectangle,y1);
      Grid.SetColumn(ScheduleRectangle,x1);

     

    The line is not being assigned a row or column, and the rectangle is. 

     

     

    Wednesday, August 18, 2010 8:05 PM
  • I get the impression that you are confused about how the grid is supposed to be used and you are trying to layout your interface with absolute (pixel) positions instead of using the power of WPF to dynamically layout your interface.

    If you want to do absolute positioning of elements, then you should use the Canvas control rather than the Grid control and set Canvas.Top and Canvas.Left to position elements. Alternatively, you can set margins on the elements you are adding to your Grid. But, either way you are kinda missing the point of WPF.

    The WPF way of doing things would be to add column and row definitions to your Grid and use auto sizing and * widths and heights to lay things out so that your application can automatically rearrange things as the size of the containing window changes. You'd then position elements by specifying which column and row a element will appear in. You can also use other panel controls such as DockPanel and StackPanel for simpler layout scenarios  (technically, anything you can do with a DockPanel or a StackPanel could be achieved by using a Grid, but it's usually easier to use the more specific panels).

    Finally, if all you want is a border, there's a Border control which you might find more suitable than either drawing a rectangle or drawing 4 lines.

    Thursday, August 19, 2010 2:47 PM

All replies

  • Yes you can easily create a rectangle in code. You'll then use the Grid.Row and Grid.Column attached properties to set its row and column and then add it to the grid's Children collection. Something like this:

     

    Rectangle rect = new Rectangle();
    .
    .
    .
    Grid.SetColumn(rect,0);   // add to column 0
    Grid.SetRow(rect,0);     // add to row 0
    
    myGrid.Children.Add(rect);
    

    Tuesday, August 17, 2010 6:58 PM
  • You can create a Rectangle with C# code and add it to your Grid through the Children property of your Grid. To assign it to a Row and/or Column you can use the SetValue() method of the Rectangle.

    yourGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
    yourGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
    
    Rectangle r = new Rectangle
    {
      Height = 25,
      Width = 25,
      Fill = new SolidColorBrush(Colors.Black)
    };
          
    r.SetValue(Grid.RowProperty, 0);
    r.SetValue(Grid.ColumnProperty, 0);
    yourGrid.Children.Add(r);
    


    Make sure you inlcude following libraries:

    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Shapes;
    

    Hope this helps.
    Tuesday, August 17, 2010 7:16 PM
  • Here's what I tried.  Doesn't work yet.  Don't know why.

     

            void DrawScheduleRectangle(int x1, int y1, int x2, int y2)
            {
               Rectangle ScheduleRectangle = new Rectangle();
               Grid.SetRow(ScheduleRectangle,y1);
               Grid.SetColumn(ScheduleRectangle,x1);
               ScheduleRectangle.Height = (y2-y1);
               ScheduleRectangle.Width = (x2-x1);
               MiscGrid.Children.Add(ScheduleRectangle);
            }

    Tuesday, August 17, 2010 7:25 PM
  • Used

     

                DrawScheduleRectangle(523,150,576,173);

    Tuesday, August 17, 2010 7:26 PM
  • What do you mean by "doesn't work"? What actually happens?

     

    At first glance, I can see that you are not setting Fill or Stroke on your rectangle, so you won't be able to see it (unless you already have a style defined in your XAML that is taking care of that).

    Tuesday, August 17, 2010 7:36 PM
  • Thanks. That fixed it (Stroke). I thought the default was Black and not Null. Sutton
    Tuesday, August 17, 2010 7:50 PM
  • Still not quite working.

    When I use:

            DrawScheduleRectangle(523,118,1099,141);
            DrawScheduleLine(523,118,1099,118);
            DrawScheduleLine(523,141,1099,141);

    the lines and rectangle do not coincide.  The rectangle is way below and starts way before the lines.  Anybody know why?  I think something is wrong in the rectangle routine that I'm missing, or I'm missing something else.

            void DrawScheduleLine(int x1, int y1, int x2, int y2)
            {
                Line ScheduleLine = new Line();
                ScheduleLine.X1 = x1;
                ScheduleLine.Y1 = y1;
                ScheduleLine.X2 = x2;
                ScheduleLine.Y2 = y2;
                ScheduleLine.Stroke = Brushes.Black;
                MiscGrid.Children.Add(ScheduleLine);
            }

            void DrawScheduleRectangle(int x1, int y1, int x2, int y2)
            {
               Rectangle ScheduleRectangle = new Rectangle();
               Grid.SetRow(ScheduleRectangle,y1);
               Grid.SetColumn(ScheduleRectangle,x1);
               ScheduleRectangle.Height = (y2-y1);
               ScheduleRectangle.Width = (x2-x1);
               ScheduleRectangle.Stroke = Brushes.Black;
               MiscGrid.Children.Add(ScheduleRectangle);
            }

    Tuesday, August 17, 2010 9:10 PM
  • Have you tried my solution? I'm not sure it is the perfect answer but you might as well give it a try. :)
    Tuesday, August 17, 2010 9:17 PM
  • Yours does the same thing, except it fills in the rectangle black.  I made another routine DrawRectangle2 to differentiate the two.  So, I'm not sure why the drastic offset in the rectangle from where the lines are drawn.  The only thing I did was to change in your code is the row and col to be y1 and x1.  So, that I could test different rectangles.

     

    Sutton

    Wednesday, August 18, 2010 1:52 AM
  • What do the first two lines in your code do?  I commented those out, but get the same offset rectangle filled black.
    Wednesday, August 18, 2010 1:56 AM
  • Those two lines are to define the rows and columns of your grid if you wouldn't have any definitions of them in your XAML code. What is it that still doesn't work yet?
    Wednesday, August 18, 2010 10:19 AM
  • See http:\\www.lookoutportablesecurity.com\sutton\rectangle.bmp

     

    The top rectangle is drawn by DrawScheduleLine (4 calls).  The bottom rectangle is drawn by both DrawScheduleRectangle1 and DrawScheduleRectangle2, but should be drawn in the same place as the first.

     

    In DrawScheduleRectangle2, the first two statements don't do anything as far as put code in my XAML section as you suggest.  And, also the RowProperty and ColumnProperty values don't do anything either.  Meaning, no matter what the values are, the rectangle is put in the exact same spot.

     

    Any ideas on why the DrawRectangle routines don't do the same as the DrawLine routine.

     

                DrawScheduleRectangle(523,118,1099,141);

                DrawScheduleRectangle2(523,118,1099,141);

                DrawScheduleLine(523,118,1099,118);
                DrawScheduleLine(523,141,1099,141);
                DrawScheduleLine(523,118,523,141);
                DrawScheduleLine(1099,118,1099,141);

     

            void DrawScheduleLine(int x1, int y1, int x2, int y2)
            {
                Line ScheduleLine = new Line();
                ScheduleLine.X1 = x1;
                ScheduleLine.Y1 = y1;
                ScheduleLine.X2 = x2;
                ScheduleLine.Y2 = y2;
                ScheduleLine.Stroke = Brushes.Black;
                MiscGrid.Children.Add(ScheduleLine);
            }

            void DrawScheduleRectangle(int x1, int y1, int x2, int y2)
            {
               Rectangle ScheduleRectangle = new Rectangle();
               Grid.SetRow(ScheduleRectangle,y1);
               Grid.SetColumn(ScheduleRectangle,x1);
               ScheduleRectangle.Height = (y2-y1);
               ScheduleRectangle.Width = (x2-x1);
               ScheduleRectangle.Stroke = Brushes.Black;
               MiscGrid.Children.Add(ScheduleRectangle);
            }

            void DrawScheduleRectangle2(int x1, int y1, int x2, int y2)
            {
               MiscGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
               MiscGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });

               Rectangle r = new Rectangle
               {
                  Height = 23,
                  Width = 576,
                  Fill = new SolidColorBrush(Colors.Black)
               };
         
               r.SetValue(Grid.RowProperty, y1);
               r.SetValue(Grid.ColumnProperty, x1);
               MiscGrid.Children.Add(r);
            }

    Wednesday, August 18, 2010 1:49 PM
  • Does your grid have rows and columns? 

    If so this is wrong.  If not it isn't doing anything anyway.

     

    Comment this out:

      Grid.SetRow(ScheduleRectangle,y1);
      Grid.SetColumn(ScheduleRectangle,x1);

     

    The line is not being assigned a row or column, and the rectangle is. 

     

     

    Wednesday, August 18, 2010 8:05 PM
  • I get the impression that you are confused about how the grid is supposed to be used and you are trying to layout your interface with absolute (pixel) positions instead of using the power of WPF to dynamically layout your interface.

    If you want to do absolute positioning of elements, then you should use the Canvas control rather than the Grid control and set Canvas.Top and Canvas.Left to position elements. Alternatively, you can set margins on the elements you are adding to your Grid. But, either way you are kinda missing the point of WPF.

    The WPF way of doing things would be to add column and row definitions to your Grid and use auto sizing and * widths and heights to lay things out so that your application can automatically rearrange things as the size of the containing window changes. You'd then position elements by specifying which column and row a element will appear in. You can also use other panel controls such as DockPanel and StackPanel for simpler layout scenarios  (technically, anything you can do with a DockPanel or a StackPanel could be achieved by using a Grid, but it's usually easier to use the more specific panels).

    Finally, if all you want is a border, there's a Border control which you might find more suitable than either drawing a rectangle or drawing 4 lines.

    Thursday, August 19, 2010 2:47 PM