3

根据文档“(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 ?
有没有办法可以设置它以便提高它?


解决方案

该测试通过了 HB 的静态类:

   [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);
        }
    }
4

2 回答 2

4

矩形由 UI 线程管理,它以排队的方式执行操作SizeChanged,在完成方法执行后很久就会触发,如果您只是设置断点或显示 MessageBox 而不是设置 bool,您会看到它确实是被解雇。

编辑:我将如何测试它;只需事先添加一些延迟:

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);
    }
}
于 2011-07-27T22:37:38.357 回答
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
}
于 2019-12-30T09:18:12.960 回答