为什么此代码中没有引发 FrameworkElement.SizeChanged

发布于 2024-11-26 11:08:16 字数 2071 浏览 2 评论 0原文

根据文档“(FrameworkElement.SizeChanged)当该元素上的 ActualHeight 或 ActualWidth 属性更改值时发生。”

运行以下测试方法,我的矩形的 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);
        }
    }

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笑叹一世浮沉 2024-12-03 11:08:16

矩形由 UI 线程管理,该线程以排队方式执行操作,如果您只是设置断点或显示 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);
    }
}

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);
    }
}
薆情海 2024-12-03 11:08:16

这实际上可以通过一行代码完成:

[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
}

This can actually be done with one line of code:

[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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文