使用自定义控件时,Silverlight错误“布局周期检测布局无法完成​​”

时间:2009-03-11 20:33:08

标签: silverlight custom-controls silverlight-2.0

我正在Silverlight中构建一个自定义控件,方法是从ContentControl派生并做一些特殊的格式化,在内容后面放置一些阴影。

我几乎让它工作但最近遇到了一个奇怪的错误。如果它包含除Border之外的任何内容,或者没有明确定义的高度和宽度的Grid / Stackpanel / etc,它可以正常工作。

我在IE中遇到JavaScript错误,文字说:

  

运行时错误4008 ...检测到布局周期...布局无法完成​​。

如果我在包含的grid / stackpanel / etc上指定高度和宽度,它可以正常工作。

当使用太多文本框(超过250个)时,网上有很多关于此错误的内容,但我可以使用网格中的单个按钮重现我的错误。

我在页面上根本没有文本框。该错误与检测到的无限循环有关。我在代码中设置了几个断点,似乎在渲染过程中会大量调用“SizeChanged”事件,每次高度/宽度增加10时。

我假设设置默认的高度/宽度会导致它跳过这个数字递增,但我不知道为什么会发生这种错误。

有没有人遇到这个或有任何想法?

5 个答案:

答案 0 :(得分:7)

有一个good blog post on this error here

基本上可能发生的事情是你在MeasureOverride某个地方改变一些尺寸会导致另一个尺寸,这会改变尺寸,从而导致测量等等。我之前遇到过这个问题并通过删除导致布局更新的任何代码或在布局周期中触发布局更新来修复它。

更新:由于博文不见了,请在此完整引用:

  

继续我对Silverlight 2的一系列问题,我想谈谈人们看到的一个常见错误。在将代码从Beta 2移动到Release Candidate或更高版本时,您可能会看到此错误。在Beta 2中,如果布局引擎检测到一个循环,它不会抛出任何错误;据我所知,布局刚刚中止。但是使用后Beta2位,会引发错误。

     

您将获得的错误将指定“检测到布局周期”作为消息。此错误消息非常准确 - 布局引擎检测到布局中的循环;或者换句话说,你的布局中有一个无限循环。

     

导致此错误的最大罪魁祸首是LayoutUpdated事件处理程序中的代码。如果您的LayoutUpdated事件处理程序执行任何操作来改变控件的布局,那么将导致LayoutUpdated事件再次触发,并再次触发......: - )

     

有时您需要在此事件处理程序中更改代码布局,那么该做什么呢?

     

首先,您应该考虑是否确实需要在每次调用LayoutUpdated时进行布局更改。是否足以处理Loaded事件以及Application.Current.Host.Content.Resized事件。在这两个事件之间,当控件加载到可视树中时,您将收到通知,并且每当主机调整大小时都会收到通知,这可能会导致您需要再次更改布局。模态对话框等场景应该属于这一类。

     

其次,如果您确实需要使用LayoutUpdated,则可能只需要在布局更改中添加一些条件。例如,如果要为控件计算新的宽度和高度,在实际设置宽度和高度之前,请检查以确保当前值与计算值不同。这将允许第一个LayoutUpdated事件调整控件的大小,从而触发另一个LayoutUpdated事件,但该事件将识别出没有工作要做,并且循环将结束。

     

当您处理SizeChanged事件时,或者您正在对控件的布局进行任何其他覆盖时,将应用这些相同的规则。

答案 1 :(得分:6)

一个常见原因是处理SizeChanged然后在处理程序中执行影响元素大小的事情。有时这并不明显 - 例如,它可能会修改影响其容器大小的子元素。

答案 2 :(得分:4)

1.如果您在ScrollViewer中使用LongListSelector,最好删除它。我遇到了同样的问题,我的LongListSelector在ScrollViewer中。在ItemRealized事件期间,出现此错误。

2.不要在itemrealized中使用updatelayout()。我正在使用像

这样的东西
 list.UpdateLayout();
 list.ScrollTo(e.Container.Content);

只需使用ScrollTo

即可

3.如果您在longlistselector中使用图像,请确保设置图像的高度和宽度。

答案 3 :(得分:1)

我有同样的问题,我所做的是将所有布局更新(大小更改)放在稍后调用的“调用”委托中,它会停止崩溃,但是你有一个很好的改变它被卡在循环中

答案 4 :(得分:0)

我遇到了同样的问题,但它只是极少发生,我的代码多年来没有改变,只是最近有人设法体验它。

我在LongListSelector DataSource中有一个TextBlock,其FontSize设置为21.将FontSize更改为ANY其他值为我修复了问题......

我的LongListSelectors位于ScrollViewer中。

            <phone:PanoramaItem x:Name="OwnedGamesPanoramaItem" >
            <ScrollViewer Margin="5,-25,0,0">
            <StackPanel>
                    <TextBlock toolkit:TiltEffect.IsTiltEnabled="True" Text="{Binding Path=LocalizedResources.XOwnedGames, Source={StaticResource LocalizedStrings}}" FontFamily="Segoe WP Semibold" CharacterSpacing="10"  FontSize="25" Margin="0,10,0,25" TextWrapping="Wrap"/>
                    <TextBlock x:Name="ownedGameLoadingTextBox" Margin="10" FontSize="26" Text="{Binding Path=LocalizedResources.XLoading, Source={StaticResource LocalizedStrings}}" HorizontalAlignment="Center"/>
                    <phone:LongListSelector x:Name="OwnedGameListBox" Tap="OwnedGameListBoxTap" ScrollViewer.VerticalScrollBarVisibility="Disabled" ItemRealized="OwnedGameListBox_ItemRealized" ItemUnrealized="OwnedGameListBox_ItemUnrealized" BorderThickness="0,20,0,0"  >
                        <phone:LongListSelector.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Vertical" Tap="OwnedGameListBoxTap" Margin="0,0,0,12">
                                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,10,0,0" Tap="StackPanel_Tap_1">
                                        <Image Width="60" Source="{Binding getSmallImageActualURL}" Height="60"  Margin="3" VerticalAlignment="Top" />
                                        <StackPanel Margin="15,0,0,0">
                                            <TextBlock Width="320" TextWrapping="Wrap" Text="{Binding name}" Margin="0,0,0,0" FontSize="32" />
                                            <TextBlock Text="{Binding getTotalPlaytimeFormatted}" Margin="0,0,0,0" TextWrapping="Wrap" FontSize="21" >
                                                <TextBlock.Foreground>
                                                    <SolidColorBrush Color="{StaticResource PhoneAccentColor}"/>
                                                </TextBlock.Foreground>
                                            </TextBlock>
                                        </StackPanel>
                                    </StackPanel>
                                </StackPanel>
                            </DataTemplate>
                        </phone:LongListSelector.ItemTemplate>
                    </phone:LongListSelector>
                </StackPanel>
            </ScrollViewer>
        </phone:PanoramaItem>

修正:

<TextBlock Text="{Binding getTotalPlaytimeFormatted}" Margin="0,0,0,0" TextWrapping="Wrap" FontSize="22" >