Ошибка Silverlight «Обнаружен цикл макета Не удалось завершить макет» при использовании пользовательского элемента управления - PullRequest
14 голосов
/ 11 марта 2009

Я создаю пользовательский элемент управления в Silverlight, производный от ContentControl и выполняя специальное форматирование, чтобы поместить тень на содержимое.

У меня почти получилось, но недавно я натолкнулся на странную ошибку. Он отлично работает, если он содержит что-либо кроме Border или Grid / Stackpanel / etc, которые не имеют явно определенных высоты и ширины.

Я получаю ошибку JavaScript в IE, и текст говорит:

Ошибка времени выполнения 4008 ... Обнаружен цикл макета ... Макет не может быть завершен.

Если я укажу высоту и ширину на сетке / панели стека / и т. Д., Она будет работать нормально.

В Интернете существует масса сообщений об этой ошибке, когда используется слишком много текстовых полей (более 250), но я могу воспроизвести свою ошибку с помощью одной кнопки в сетке.

У меня вообще нет текстовых полей на странице. Ошибка связана с обнаруженным бесконечным циклом. Я установил несколько точек останова в коде, и кажется, что событие «SizeChanged» часто вызывается во время рендеринга, и каждый раз высота / ширина увеличивается на 10.

Я предполагаю, что установка высоты / ширины по умолчанию заставляет его пропускать это увеличение числа, но я понятия не имею, почему происходит эта ошибка.

Кто-нибудь сталкивался с этим или есть какие-нибудь идеи?

Ответы [ 5 ]

7 голосов
/ 12 марта 2009

Здесь есть хорошее сообщение об этой ошибке .

Главное, что может произойти, это то, что вы меняете некоторый размер в MeasureOverride где-то, что вызывает другую меру, которая изменяет размер, который вызывает меру и так далее. Я однажды столкнулся с этим и исправил его, удалив любой код, который вызвал обновление макета или вызвал обновление макета во время цикла макета.

Обновление: поскольку сообщение в блоге исчезло, приведу его здесь полностью:

Продолжая серию ошибок для Silverlight 2, я хотел рассказать об общей ошибке, которую видят люди. Эта ошибка является чем-то новым, что вы можете увидеть при переносе кода из Beta 2 в Release Candidate или позже. В бета-версии 2, если механизм верстки обнаружил цикл, он не выдавал никаких ошибок; насколько я понимаю, макет был просто прерван. Но с битами после Beta2 выдается ошибка.

При появлении сообщения об ошибке в качестве сообщения будет указан «Layout Cycle Detected». Это сообщение об ошибке очень точное - механизм макета обнаружил цикл в вашем макете; или иначе, у вас есть бесконечный цикл в макете.

Самым большим виновником этой ошибки является код в обработчике событий LayoutUpdated. Если ваш обработчик событий LayoutUpdated что-либо изменит для макета вашего элемента управления, то это вызовет повторное инициирование события LayoutUpdated, и снова, и снова ...: -)

Иногда вам нужно иметь код, изменяющий компоновку в этом обработчике событий, так что же делать?

Во-первых, вы должны подумать, действительно ли вам нужно, чтобы изменения макета происходили при каждом вызове LayoutUpdated. Достаточно ли будет обработать событие Loaded, а также событие Application.Current.Host.Content.Resized. Между этими двумя событиями вы получите уведомление, когда элемент управления будет загружен в визуальное дерево, и вы будете получать уведомления каждый раз, когда размер хоста изменяется, что может потребовать повторного изменения макета. Сценарии, такие как модальные диалоги, должны попадать в эту категорию.

Во-вторых, если вам действительно нужно использовать LayoutUpdated, возможно, вам просто нужно наложить некоторые условия на изменения макета. Например, если вы рассчитываете новую ширину и высоту для своего элемента управления, прежде чем вы на самом деле установите ширину и высоту, убедитесь, что текущие значения отличаются от того, что вы рассчитали. Это позволит первому событию LayoutUpdated изменить размер вашего элемента управления, что вызовет другое событие LayoutUpdated, но это событие распознает, что не нужно выполнять никаких действий, и цикл завершится.

Эти же правила будут применяться при обработке события SizeChanged или при любых других переопределениях макета элемента управления.

6 голосов
/ 12 марта 2009

Распространенной причиной является обработка SizeChanged, а затем в обработчике происходит что-то, что влияет на размер элемента. Иногда это неочевидно - это могут быть модифицированные дочерние элементы, которые, например, влияют на размер их контейнера.

4 голосов
/ 06 марта 2014

1.Если вы используете LongListSelector внутри ScrollViewer, лучше удалите это. Я столкнулся с той же проблемой, и мой LongListSelector был внутри ScrollViewer. Во время события ItemRealized получала эту ошибку.

2.Не используйте updatelayout () внутри itemrealized .. Я использовал что-то вроде

 list.UpdateLayout();
 list.ScrollTo(e.Container.Content);

Просто используйте ScrollTo

3.Если вы используете изображение внутри longlistselector, обязательно установите высоту и ширину изображения.

1 голос
/ 17 мая 2011

У меня была та же проблема, и я поместил все обновления макета (изменения размера) в делегат "invoke", который вызывается позже, он перестает падать, но есть хорошее изменение, он застрял в цикле

0 голосов
/ 12 мая 2015

У меня была такая же проблема, но она возникала крайне редко, мой код не менялся годами, и только недавно кому-то это удалось.

У меня был TextBlock внутри LongListSelector DataSource, и его FontSize был установлен на 21. Изменение FontSize на ЛЮБОЕ другое значение устранило проблему для меня ...

Мой 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>

Fix:

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