根据文档“(FrameworkElement.SizeChanged)当ActualHeight或ActualWidth属性更改此元素的值时发生。”
运行以下测试方法后,我的Rectangle的ActualWidth和ActualHeight在调用Measure和Arrange后会更新,但是从不会引发SizeChanged RoutedEvent。
[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
}
有人可以解释为什么不提出SizeChanged吗? 有没有办法可以设置它以便它被提升?
解
在H.B.的静态类中滑动,此测试通过:
[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);
}
}
答案 0 :(得分:3)
矩形由UI线程管理,它以排队方式执行操作,SizeChanged
在完成方法执行后很长时间触发,如果您只是设置断点或显示MessageBox而不是设置布尔,你会发现它确实被解雇了。
修改:我将如何进行测试;只是事先添加一些延迟:
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);
}
}
答案 1 :(得分:0)
这实际上可以用一行代码来完成:
[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));
// this is equivalent to Application.DoEvents() in WinForms.
// we need this because events need to be fired before the method ends
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new Action(() => { }));
//r.ActualWidth and r.ActualHeight are now both 5.
Assert.That(sizeChangedRaised);// false
}