为什么在此代码中未引发FrameworkElement.SizeChanged

时间:2011-07-27 22:03:55

标签: wpf unit-testing routed-events

根据文档“(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);
        }
    }

2 个答案:

答案 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
}