2009-03-11 15 views
13

Sto costruendo un controllo personalizzato in Silverlight derivando da ContentControl e facendo alcune formattazioni speciali per mettere un dropshadow dietro il contenuto.Errore Silverlight "Impossibile completare il layout Rilevato ciclo layout" quando si utilizza il controllo personalizzato

Ho quasi funzionato, ma di recente ho avuto un bizzarro errore. Funziona bene se contiene qualcosa oltre a un Border, o un Grid/Stackpanel/etc che non ha un'altezza e una larghezza definite in modo esplicito.

ottengo un errore JavaScript in IE, e il testo dice:

Errore di runtime 4008 ... layout Ciclo rilevato ... layout Impossibile completare.

Se specifico un altezza e larghezza sulla griglia di partenza/StackPanel contenute/etc funziona benissimo.

C'è una tonnellata sul web riguardo a questo errore quando si usano troppe caselle di testo (oltre 250), ma sono in grado di riprodurre il mio errore con un singolo pulsante in una griglia.

Non ho nessuna casella di testo nella pagina. L'errore ha a che fare con un loop infinito rilevato. Ho impostato alcuni punti di interruzione nel codice e sembra che l'evento "SizeChanged" venga richiamato molto durante il rendering e ogni volta l'altezza/larghezza aumenta di 10.

Suppongo che l'impostazione di un'altezza predefinita/width lo fa saltare questo incremento del numero, ma non ho idea del perché questo errore stia accadendo.

Qualcuno si è imbattuto in questo o ha qualche idea?

+0

Ho incontrato questo problema con il controllo del Telerik RadWindow (sarebbe probabilmente accadrà anche con la childWindow regolare). Il problema si è verificato quando ho specificato MinHeight e MinWidth senza specificare Larghezza e Altezza. Quando la dimensione del contenuto della finestra è cambiata, si è verificato un ciclo di layout. L'impostazione di Larghezza e Altezza sugli stessi valori di MinWidth e MinHeight ha risolto il problema. –

risposta

7

C'è un good blog post on this error here.

Bascially quello che può succedere è che stai cambiando alcune dimensioni in un MeasureOverride da qualche parte che provoca un'altra misura, che cambia le dimensioni, che causa una misura e così via. Mi sono imbattuto in questo caso e l'ho risolto rimuovendo qualsiasi codice che causasse un aggiornamento del layout o attivato un aggiornamento del layout durante il ciclo di layout.

Aggiornamento: Dal momento che il post è andato, citando qui per intero:

Continuando la mia serie di trucchi per Silverlight 2, ho voluto parlare di un errore comune che le persone stanno vedendo. Questo errore è qualcosa di nuovo che potresti vedere quando sposti codice da Beta 2 a Release Candidate o successivo. Nella Beta 2, se il motore di layout ha rilevato un ciclo, non ha generato alcun errore; a quanto ho capito, il layout è stato appena abortito. Ma con i bit post Beta2, viene generato un errore.

L'errore che verrà visualizzato specificherà "Rilevato ciclo di layout" come messaggio. Questo messaggio di errore è molto accurato: il motore di layout ha rilevato un ciclo all'interno del layout; o un altro modo per dirlo, hai un ciclo infinito nel tuo layout.

Il principale colpevole che porta a questo errore è il codice all'interno del gestore di eventi LayoutUpdated. Se il tuo gestore di eventi LayoutUpdated fa qualcosa per alterare il layout del tuo controllo, allora l'evento LayoutUpdated si accenderà di nuovo, e ancora e ancora ... :-)

A volte è necessario avere all'interno del codice di modifica del layout questo gestore di eventi però, quindi cosa si può fare?

In primo luogo, è necessario considerare se è veramente necessario che le modifiche al layout si verifichino su ogni chiamata a LayoutUpdated. Sarebbe sufficiente gestire l'evento Loaded e l'evento Application.Current.Host.Content.Resized. Tra questi due eventi, riceverai una notifica quando il controllo viene caricato nell'albero visivo e riceverai una notifica ogni volta che l'host viene ridimensionato, il che potrebbe causare la necessità di modificare nuovamente il layout. Scenari come i dialoghi modali dovrebbero rientrare in questa categoria.

In secondo luogo, se è davvero necessario utilizzare LayoutUpdated, è possibile che sia necessario impostare alcune condizioni attorno alle modifiche del layout. Ad esempio, se si sta calcolando una nuova larghezza e altezza per il controllo, prima di impostare effettivamente la larghezza e l'altezza, verificare che i valori correnti differiscano da quelli calcolati. Ciò consentirà al primo evento di LayoutUpdated di ridimensionare il controllo, che attiva un altro evento di LayoutUpdated, ma quell'evento riconoscerà che non c'è lavoro da fare e il ciclo terminerà.

Queste stesse regole si applicano quando si gestisce l'evento SizeChanged o se si stanno eseguendo altre sostituzioni sul layout del proprio controllo.

+0

Questo è il problema che sto vedendo. Il post sul blog collegato suggerisce di fare solo le cose del tuo layout al caricamento iniziale e quando l'app silverlight (il controllo utente contenente) modifica le sue dimensioni.Questo potrebbe funzionare per me, ma non l'ho ancora testato durante le animazioni e altre azioni. Grazie per l'aiuto! –

+0

@bryant blog dead; ( – MemeDeveloper

+0

Wayback machine in the rescue: https://web.archive.org/web/20110203182929/http://jeffhandley.com/archive/2008/09/26/silverlight-2-post- beta2-Gotcha --- layout ciclo-detected.aspx – Bryant

6

Una causa comune è la gestione di SizeChanged e quindi nel gestore che fa qualcosa che influenza la dimensione dell'elemento. A volte questo non è ovvio - potrebbe modificare elementi figlio che influenzano la dimensione del loro contenitore, per esempio.

1

Ho avuto lo stesso problema e quello che ho fatto è stato messo tutti gli aggiornamenti di layout (variazioni di dimensioni) in un delegato "invocare" en invocato più tardi, si ferma crash ma c'è un buon cambiamento è bloccato in un ciclo

4

1.Se si utilizza LongListSelector in ScrollViewer, è meglio rimuoverlo. Stavo affrontando lo stesso problema e il mio LongListSelector era all'interno di ScrollViewer. Durante l'evento ItemRealized, stava ottenendo questo errore.

non uso 2.Do UpdateLayout() all'interno itemrealized..I stava usando qualcosa come

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

Basta usare scrollTo

3.Se si utilizza immagine all'interno longlistselector, assicurarsi di impostare l'altezza e la larghezza dell'immagine.

0

Ho avuto lo stesso problema ma si è verificato solo molto raramente, il mio codice non è cambiato da anni e solo recentemente qualcuno è riuscito a viverlo.

ho avuto un TextBlock all'interno di un DataSource LongListSelector e la sua FontSize è stato fissato a 21. La modifica della FontSize a qualsiasi altro valore fisso il problema per me ...

miei LongListSelectors è all'interno di uno 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" > 
Problemi correlati