Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force ActualWidth and ActualHeight to update (silverlight)

I a grid on my silverlight control, I am programatically adding a canvas, and in the canvas I am loading and displaying Image.

I'm also adding a rotation to the canvas. The problem is that by default the CenterX and CenterY of the rotation is the top left of the canvas. What I want is the rotation to happen around the centre of the canvas.

To do this, I've tried setting the CenterX and CenterY of the Rotation to the Images ActualWidth / 2 and ActualHeight / 2, however I've discovered that ActualWidth and ActualHeight are not always populated, at least not right away. How can I force them to get updated?

Even using the DownloadProgress event on the image doesn't seem to guarantee the ActualWidth and ActualHeight are populated, and neither does using this.Dispatcher.BeginInvoke()...

Image imgTest = new Image();
Canvas cnvTest = new Canvas();
Uri uriImage = new Uri("myurl", UriKind.RelativeOrAbsolute);
System.Windows.Media.Imaging.BitmapImage bmpDisplay = new System.Windows.Media.Imaging.BitmapImage(uriImage);

bmpDisplay.DownloadProgress += new EventHandler<System.Windows.Media.Imaging.DownloadProgressEventArgs>(this.GetActualDimensionsAfterDownload);

imgTest.Source = bmpDisplay;
imgTest.Stretch = Stretch.Uniform;
imgTest.HorizontalAlignment = HorizontalAlignment.Center;
imgTest.VerticalAlignment = VerticalAlignment.Center;

cnvTest.Children.Add(imgTest);

this.grdLayout.Children.Add(imgTest);
this.Dispatcher.BeginInvoke(new Action(GetActualDimensions)); 
like image 376
Jeremy Avatar asked Aug 10 '09 20:08

Jeremy


3 Answers

To update the ActualWidth and ActualHeight of a FrameworkElement you will have to call UpdateLayout.

like image 150
Martin Liversage Avatar answered Nov 01 '22 11:11

Martin Liversage


Unfortunately, calling updateLayout doesn't always work either depending on your situation.

I've had better luck doing something like:

whateverUIElement.Dispatcher.BeginInvoke(()
  {
   //code that needs width/height here
  }
);

but even that fails too often.

like image 25
dethSwatch Avatar answered Nov 01 '22 10:11

dethSwatch


Most reliable method I found is to use DependencyPropertyDescriptor AddValueChanged listeners of ActualWidth and ActualHeight instead of OnLayoutUpdated to get element sizes after rendering

DependencyPropertyDescriptor descriptor = DependencyPropertyDescriptor.FromProperty(ActualWidthProperty, typeof(StackPanel));
if (descriptor != null)
{
    descriptor.AddValueChanged(uiPanelRoot, DrawPipelines_LayoutUpdated);
}

descriptor = DependencyPropertyDescriptor.FromProperty(ActualHeightProperty, typeof(StackPanel));
if (descriptor != null)
{
    descriptor.AddValueChanged(uiPanelRoot, DrawPipelines_LayoutUpdated);
}


void DrawPipelines_LayoutUpdated(object sender, EventArgs e)
{
    // Point point1 = elementInstrumentSampleVial.TranslatePoint(
    //                new Point(11.0, 15.0), uiGridMainInner);
}

Instead of using StackPanel, Grid etc. use base element that you are depending on for relative sizes

like image 41
Evalds Urtans Avatar answered Nov 01 '22 09:11

Evalds Urtans