我正在Silverlight中构建一个自定义控件,它是从ContentControl派生出来并做一些特殊的格式化,在内容后面放置一些阴影.
我几乎得到了它的工作,但最近遇到了一个奇怪的错误.如果它包含除Border之外的任何内容,或者没有明确定义的高度和宽度的Grid/Stackpanel/etc,它可以正常工作.
我在IE中遇到JavaScript错误,文字说:
运行时错误4008 ...检测到布局周期...布局无法完成.
如果我在包含的grid/stackpanel/etc上指定高度和宽度,它可以正常工作.
当使用太多文本框(超过250个)时,网上有关于此错误的信息,但我可以使用网格中的单个按钮重现我的错误.
我在页面上根本没有文本框.该错误与检测到的无限循环有关.我在代码中设置了几个断点,似乎在渲染过程中会大量调用"SizeChanged"事件,每次高度/宽度增加10.
我假设设置一个默认的高度/宽度会导致它跳过这个数字递增,但我不知道为什么会发生这个错误.
有没有人碰到这个或有任何想法?
这里有关于此错误的好文章.
基本上可能发生的事情是你在MeasureOverride
某个地方改变一些尺寸会导致另一个尺寸,这会改变尺寸,从而导致一个尺度等等.之前我碰到过这个并通过删除导致布局更新的任何代码或在布局周期中触发布局更新来修复它.
更新:由于博客文章已经消失,请在此完整引用:
继续我对Silverlight 2的一系列问题,我想谈谈人们看到的一个常见错误.在将代码从Beta 2移动到Release Candidate或更高版本时,您可能会看到此错误.在Beta 2中,如果布局引擎检测到一个循环,它不会抛出任何错误; 据我所知,布局刚刚中止.但是对于后Beta2位,会抛出错误.
您将获得的错误将指定"检测到布局周期"作为消息.此错误消息非常准确 - 布局引擎检测到布局中的循环; 或者换句话说,你的布局中有一个无限循环.
导致此错误的最大罪魁祸首是LayoutUpdated事件处理程序中的代码.如果您的LayoutUpdated事件处理程序执行任何操作来改变控件的布局,那么将导致LayoutUpdated事件再次触发,并再次触发...... :-)
有时您需要在此事件处理程序中更改代码布局,那么该做什么呢?
首先,您应该考虑是否确实需要在每次调用LayoutUpdated时进行布局更改.是否足以处理Loaded事件以及Application.Current.Host.Content.Resized事件.在这两个事件之间,当控件加载到可视树中时,您将收到通知,并且每当主机调整大小时都会收到通知,这可能会导致您需要再次更改布局.模态对话框等场景应属于此类别.
其次,如果您确实需要使用LayoutUpdated,则可能只需要在布局更改中添加一些条件.例如,如果要为控件计算新的宽度和高度,在实际设置宽度和高度之前,请检查以确保当前值与计算值不同.这将允许第一个LayoutUpdated事件调整控件的大小,从而触发另一个LayoutUpdated事件,但该事件将识别出没有工作要做,并且循环将结束.
当您处理SizeChanged事件时,或者您正在对控件的布局进行任何其他覆盖时,将应用这些相同的规则.
一个常见的原因是处理SizeChanged
,然后在处理程序中做一些影响元素大小的事情.有时这并不明显 - 例如,它可能会修改影响其容器大小的子元素.