I am working on a Drag and Drop Editor that is creating items and adding them dynamically to a WPF Canvas. For each item, it is creating a dynamic grid and addign that to the canvas. I need layout state information about each one of these grids as it is added so that I know its coordinates on the canvas. The problem I am having is that when I try to access the Height/ActualHeight/RenderedSize information of each of these Grids that I add, it always turns out to be 0. I am assuming that I might need to render the items so that the new state information is registered, but I am not quite sure how to do this. I have seen support through the InvalidateXXXX() methods that are provided, but I am not sure if/or which one I should be using. there is also an UpdateLayout() function, but I am not sure if this is what I need.
Here is the code that I have running through a loop and adding Grids, which represent LineItems in the Canvas.
/*Initialize Grid Layout*/
Grid newGrid = new Grid();
newGrid.MinHeight = 50;
newGrid.Width = PreviewWindow.ActualWidth;
newGrid.Background = Brushes.Beige;
newGrid.ShowGridLines = true;
/*Define Column Definitions*/
List<ColumnDefinition> columns = new List<ColumnDefinition>(fieldItemList.Count);
foreach (ColumnDefinition column in columns)
{
ColumnDefinition labelColumn = new ColumnDefinition();
newGrid.ColumnDefinitions.Add(labelColumn);
newGrid.ColumnDefinitions.Add(column);
}
/*Define Row Definitions*/
RowDefinition row = new RowDefinition();
newGrid.RowDefinitions.Add(row);
int colCount = 0;
for (int i = 0; i < fieldItemList.Count; i++)
{
FieldItem fieldItem = fieldItemList[i];
/*Initialize Example Label*/
Label label = new Label();
label.Content = fieldItem.Label;
Grid.SetRow(label, 0);
Grid.SetColumn(label, colCount);
newGrid.Children.Add(label);
/*Initialize Example Text Box*/
TextBox textBox = new TextBox();
Grid.SetRow(textBox, 0);
Grid.SetColumn(textBox, colCount + 1);
newGrid.Children.Add(textBox);
colCount++;
}
stackPanel.Children.Add(newGrid);
//I need to Access the Height of each of the grids here somehow
lastTop += (int)newGrid.ActualHeight ;
newGrid.InvalidateMeasure();
//Or InvalidateVisual(), or do I perform this on something else?
}
There is reference to a StackPanel, all of these Grids are being added to a stack panel, and they will eventuall be arranged by the coordinates(which I currently cannot grab). The problem is right now it is adding all these items to a list that will need to be sorted by the Top coordinate, but since the Top coordinate is 0, it will not sort correctly.
A few notes:
The StackPanel does not provide size Layout suggestions to its children, so the Grid will need to supply it’s own Layout size. In order for this to work, you’ll need to set the Row and Column sizes to “Auto” so that they expand to accommodate their contents. Even then, I’m not entirely sure if this works (usually you combine Auto with “*” rows or columns, rather than having all Auto columns, having them expand to a fixed or stretched overall Grid size.) The layout I’ve proposed here will behave a bit oddly, as it will dynamically resize columns based on the contents of the column text boxes; for instance, if you have no text in any row, you’ll get zero width text boxes with only margin and border providing any size.
Once the StackPanel has had its children added, you’ll need to call UpdateLayout on the StackPanel. This will cause it to compute the layout information for each of its children and then position them appropriately. This can become expensive if you keep adding grids dynamically, so fair warning.