Larry S
Larry S

Reputation: 457

Centering or manually positioning dynamic controls on a WPF Canvas

I'm trying to create Labels that are centered around different columns on a Canvas. This code looks plausible:

string[] titles = { "Acorn", "Banana", "Chrysanthemum" };
double col = 20.0;
foreach (string s in titles) 
{
    var lbl = new Label() { Content = s };
    lbl.SetValue(Canvas.LeftProperty, col - (lbl.Width / 2.0));
    myCanvas.Children.Add(lbl);
    col += 150.0;
}

But it does not work because the lbl.Width (and lbl.ActualWidth) aren't calculated until rendering, which is long after the Labels are being created.

Is there a way to get the accurate Label.Width prior to a layout operation? On a Canvas there isn't all the control layout and flow you get with Grids or StackPanels.

Upvotes: 0

Views: 828

Answers (3)

Larry S
Larry S

Reputation: 457

The trick is to ask the component what size it wants to be with the Measure method. If you specify unlimited available space with the double.PositiveInfinity value, you can then use the control's DesiredSize property to get its ideal, unclipped, unflowed size.

This code shows the working solution:

  string[] titles = { "Acorn", "Banana", "Chrysanthemum" };
  double col = 20.0;
  foreach (string s in titles) {
    var lbl = new Label() { Content = s };
    lbl.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    lbl.SetValue(Canvas.LeftProperty, col - (lbl.DesiredSize.Width / 2.0));
    myCanvas.Children.Add(lbl);
    col += 150.0;
  }

Upvotes: 1

sa_ddam213
sa_ddam213

Reputation: 43596

Have you tried:

double pos = Canvas.GetLeft(lbl);

I'm not sure if this works before the layout pass, but worth a shot

Upvotes: 0

Mark
Mark

Reputation: 14930

You cant get the width before a layout pass... But what you could try is setting the Label to Visibility of Hidden (not Collapsed), then attach a Loaded event, and set its position then change back the visibility?

Upvotes: 0

Related Questions