Search code examples
c#wpfcanvas

In WPF how to add textbox to a collection in canvas dynamically


learning WPF... I have a canvas and I have this structure:

  LayoutCanvas
  ----Mastergrid
      ----ChildGrid1
          ----Rectangle1
          ----Rectangle2
          ----Texbox1
      ----ChildGrid2
          ----Rectangle1
          ----Rectangle2
          ----Texbox1
etc..

When the user clicks on the canvas, a new childGrid gets created which houses rectangles and texboxes and that childGrid gets added to the masterGrid that houses all the childGrids. I need to be able to move the whole childGrid around in the canvas. My problem is that I'm unable to position the textbox wherever I want within its parent grid (the childGrid). Adding the textbox goes automatically to the center of its masterGrid. Here is my code, what am I doing wrong or how else to achieve it.

Grid masterGrid = new Grid();
masterGrid.Width = 600;
masterGrid.Height = 600;

Grid childGrid = new Grid();
childGrid.Width = 100;
childGrid.Height = 100;
Canvas.SetLeft(childGrid, 100);
Canvas.SetTop(childGrid, 100);
masterGrid.Children.Add(childGrid);

var txt = new TextBox();
txt.Text = "New Text1";
Canvas.SetLeft(txt, 10);
Canvas.SetTop(txt, 10);
txt.Width = 100;
txt.Height = 100;
childGrid.Children.Add(txt);

LayoutCanvas.Children.Add(masterGrid);

EDIT Thank you Greg M for the explanation, but when I try to play with this example, I get my textbox showing up in the same exact spot for 2 or 3 for the rowProperty value, but with 1, the textbox does go up:

Grid masterGrid = new Grid
{
    Width = 600,
    Height = 600
};

masterGrid.ColumnDefinitions.Add(new ColumnDefinition());
masterGrid.RowDefinitions.Add(new RowDefinition());
masterGrid.RowDefinitions.Add(new RowDefinition());
masterGrid.RowDefinitions.Add(new RowDefinition());

masterGrid.Width = 600;
masterGrid.Height = 600;

Grid childGrid = new Grid();
childGrid.Width = 100;
childGrid.Height = 100;
childGrid.SetValue(Grid.RowProperty, 1);
childGrid.SetValue(Grid.ColumnProperty, 1);
Canvas.SetLeft(childGrid, 100);
Canvas.SetTop(childGrid, 100);

var txt = new TextBox();
txt.Text = "New Text1";
Canvas.SetLeft(txt, 10);
Canvas.SetTop(txt, 10);
txt.Width = 100;
txt.Height = 100;

childGrid.Children.Add(txt);
masterGrid.Children.Add(childGrid);
LayoutCanvas.Children.Add(masterGrid);

Solution

  • That is because, as written, all controls are going to Row=0,Col=0.

    You are missing:

    masterGrid.ColumnDefinitions.Add(new ColumnDefinition());
    masterGrid.RowDefinitions.Add(new RowDefinition());
    

    Then you assign control to row/col:

    Grid.SetRow(childGrid, 4);
    

    so complete would look like this:

    Grid masterGrid = new Grid();
    masterGrid.ColumnDefinitions.Add(new ColumnDefinition());
    masterGrid.RowDefinitions.Add(new RowDefinition());
    masterGrid.RowDefinitions.Add(new RowDefinition());
    masterGrid.RowDefinitions.Add(new RowDefinition());
    
    Grid childGrid = new Grid();
    Grid.SetRow(childGrid, 1);
    Grid.SetColumn(childGrid, 1);
    masterGrid.Children.Add(childGrid);
    

    Your calls:

    Canvas.SetLeft(childGrid, 100);
    Canvas.SetTop(childGrid, 100);
    

    were probably meant for masterGrid? But they have no effect on childGrid since its parent is masterGrid.

    or change

    Grid childGrid to Canvas childCanvas

    To answer your edited question: If you want to be able to drag and move child grids, then you really don't want them inside another grid. You should be adding them to a canvas. You still need to write code to capture mousedown/drag events to move. (not good code, but will show you things to learn)

        CreateGridCanvas ( 10, 10, "text 1a", "text 1b" );
        CreateGridCanvas ( 20, 210, "text 2a", "text 2b" );
    
    
      private void CreateGridCanvas ( int x, int y, string text1, string text2 )
      {
        Grid childGrid = new Grid
        {
          Width = 100,
          Height = 100,
          ShowGridLines = true
        };
        LayoutCanvas.Children.Add ( childGrid );
        Canvas.SetLeft ( childGrid, x );
        Canvas.SetTop ( childGrid, y );
        //masterGrid.Children.Add ( childGrid );
        Grid.SetRow ( childGrid, 0 );
        Grid.SetColumn ( childGrid, 0 );
    
        childGrid.ColumnDefinitions.Add ( new ColumnDefinition () );
        childGrid.RowDefinitions.Add ( new RowDefinition () );
        childGrid.RowDefinitions.Add ( new RowDefinition () );
    
        TextBox txt = new TextBox
        {
          Text = text1,
          Width = 100,
          Height = 100,
          Visibility = Visibility.Visible
        };
        childGrid.Children.Add ( txt );
        Grid.SetRow ( txt, 0 );
        Grid.SetColumn ( txt, 0 );
    
        TextBox txt2 = new TextBox
        {
          Text = text2,
          Width = 100,
          Height = 100,
          Visibility = Visibility.Visible
        };
        childGrid.Children.Add ( txt2 );
        Grid.SetRow ( txt2, 1 );
        Grid.SetColumn ( txt2, 0 );
      }