According to the documentation "(FrameworkElement.SizeChanged) Occurs when either the ActualHeight or the ActualWidth properties change value on this element."
Running the following test method, my Rectangle's ActualWidth and ActualHeight are updated after calling Measure and Arrange, however the SizeChanged RoutedEvent is never raised.
[Test]
[RequiresSTA]
public void Test_Something()
{
bool sizeChangedRaised = false;
var r = new Rectangle { Width = 10, Height = 10 };
r.Measure(new Size(20, 20));
r.Arrange(new Rect(0, 0, 20, 20));
//r.ActualWidth and r.ActualHeight are both 10 at this point.
r.SizeChanged += (s, e) => sizeChangedRaised = true;
r.Width = 5;
r.Height = 5;
r.Measure(new Size(20, 20));
r.Arrange(new Rect(0, 0, 20, 20));
//r.ActualWidth and r.ActualHeight are now both 5.
Assert.That(sizeChangedRaised);// false
}
Can anyone explain why SizeChanged isn't raised?
Is there a way I can set things up so that it is raised?
SOLUTION
Slipping in H.B.'s static class this test passes:
[Test]
[RequiresSTA]
public void Test_Something()
{
bool sizeChangedRaised = false;
var r = new Rectangle { Width = 10, Height = 10 };
r.Measure(new Size(20, 20));
r.Arrange(new Rect(0, 0, 20, 20));
r.SizeChanged += (s, e) => {
sizeChangedRaised = true;
};
r.Width = 5;
r.Height = 5;
r.Measure(new Size(20, 20));
r.Arrange(new Rect(0, 0, 20, 20));
ThreadEx.Wait(1000);
Assert.That(sizeChangedRaised);
}
static class ThreadEx
{
public static void Wait(int millisecondsTimeout)
{
Wait(TimeSpan.FromMilliseconds(millisecondsTimeout));
}
public static void Wait(TimeSpan timeout)
{
var frame = new DispatcherFrame();
new Thread(() =>
{
Thread.Sleep(timeout);
frame.Continue = false;
}).Start();
Dispatcher.PushFrame(frame);
}
}
The rectangle is managed by the UI-thread which does things in a queued manner, the SizeChanged
fires long after the complete method has been executed, if you just set a breakpoint or show a MessageBox instead of setting a bool you will see that it indeed is being fired.
Edit: How i would go about testing it; just add some delay beforehand:
ThreadEx.Wait(1000);
Assert.That(sizeChangedRaised);
static class ThreadEx
{
public static void Wait(int millisecondsTimeout)
{
Wait(TimeSpan.FromMilliseconds(millisecondsTimeout));
}
public static void Wait(TimeSpan timeout)
{
var frame = new DispatcherFrame();
new Thread((ThreadStart)(() =>
{
Thread.Sleep(timeout);
frame.Continue = false;
})).Start();
Dispatcher.PushFrame(frame);
}
}