Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layout cycle detected (crash) for some list view sizes when scrolling to end of listview #6218

Closed
wbokkers opened this issue Nov 2, 2021 · 61 comments
Labels
area-Lists ListView, GridView, ListBox, etc area-Scrolling bug Something isn't working Crash whenever user reports a crash or app freeze needs-triage Issue needs to be triaged by the area owners product-winui3 WinUI 3 issues Regression team-Controls Issue for the Controls team
Milestone

Comments

@wbokkers
Copy link

wbokkers commented Nov 2, 2021

Describe the bug

I have a list view with group headers and a data template that had no issues in UWP and WinUI 3 WinAppSDK 0.8.

In WinAppSDK 1.0 Preview 3, when scrolling to the end of the list view, I get a layout cycle detected exception. But this is only the case when the listview is of a particular size. Most sizes work fine, though. The size for which the crash happens probably depends on the listview contents, but I am not sure about that.

Steps to reproduce the bug (crash on user interaction)

This issue can be reproduced using this test control:
https://gist.github.com/wbokkers/4a07fedfb99d49d4b8e8ff62971d4eb8

  1. Use the test control in a WinUI 3 WASDK 1.0 project.
  2. Click on the Next Seed button. This will choose random content and list box sizes for each seed.
  3. See when the app crashes. (most of the time it crashes on seed 9, sometimes it skips 9 and crashes on larger seed)

NOTE: Most of the time the app crashes right away for seed 9. Sometimes you need to scroll up and down using the touch pad to get the exception.

Reproduce using less code/XAML (crash on load)

The issue can be reproduced with even less and simpler code:
https://gist.github.com/wbokkers/011011af9bf95066967bd4998dca9d77

  1. Use this test control in a WinUI WASDK 1.0 project.
  2. Show the control.
  3. Crash

(For non-crashing situations: change the initial _seed or the listview height in the source code)

Expected behavior

There should be no layout cycle detected exception.

NuGet package version

WinUI 3 - Windows App SDK 1.0 Preview 3

Device form factor

Desktop

Windows version

May 2021 Update (19043)

@ghost ghost added the needs-triage Issue needs to be triaged by the area owners label Nov 2, 2021
@wbokkers
Copy link
Author

wbokkers commented Nov 4, 2021

image

@wbokkers wbokkers changed the title Layout cycle detected (crash) for some parent control sizes when scrolling to end of listview Layout cycle detected (crash) for some list view sizes when scrolling to end of listview Nov 4, 2021
@StephenLPeters
Copy link
Contributor

@RBrid and @codendone FYI

@wbokkers
Copy link
Author

This issue is happening all over the place where I am using listviews. It also happens for lists without group headers.
It really needs to be fixed in 1.0 for the product to be stable.

@wbokkers
Copy link
Author

Any news on this issue that is blocking our project for weeks now? @gabbybilka, @marb2000, @ryandemopoulos, @SavoySchuler

@gabbybilka
Copy link
Member

@wbokkers is this still occurring in 1.0?

@wbokkers
Copy link
Author

@gabbybilka Yes, it occurs mainly in 1.0. It is a very frequent crash. I think I have seen this occur in 0.8 as well, but only a couple of times.

@wbokkers
Copy link
Author

wbokkers commented Nov 24, 2021

I added a new way to reproduce this issue. It's just a matter of using the test control to immediately crash the app.
There's nothing wrong with my code. Using most other list view heights and contents will work as expected. But it's just happening way too often in real world scenario's.

@wbokkers
Copy link
Author

wbokkers commented Dec 3, 2021

@gabbybilka Any news on this and other open issues? The silence is deafening. 🦻

@MikeHillberg
Copy link
Contributor

It's getting into an infinite loop where layout A is triggering a response to change layout to B, and that's triggering a response to change layout to A, B, A, ... until it hits the max layout count. Certainly that's not supposed to happen, but it appears to be an issue in the ScrollBar track layout code getting triggered by ItemsStackPanel.ItemsUpdatingScrollMode; removing that stops the cycle:

<ListView.ItemsPanel>
    <ItemsPanelTemplate>
        <ItemsStackPanel VerticalAlignment="Bottom" ItemsUpdatingScrollMode="KeepLastItemInView" />
    </ItemsPanelTemplate>
</ListView.ItemsPanel>

@wbokkers
Copy link
Author

wbokkers commented Dec 7, 2021

@MikeHillberg Thanks for locating what's causing this issue. Unfortunately, removing ItemsUpdatingScrollMode is not an option. I need to keep the last item in view as soon as one arrives in the list view. (it's a chat-like experience).

Removing ItemsUpdatingScrollMode and using my own code to scroll to the last item will also trigger a layout cycle (less frequent) and I can't always get it to scroll down completely using this method. So there's no good workaround.

It would be great if this issue could be resolved in the 1.0 release as a quality update.

(edit: tried to use a less irritated and impatient tone.. not my forte)

@wbokkers
Copy link
Author

@MikeHillberg @gabbybilka Any news on the status?

This is the crash report of te latest version of our app, with Windows App SDK 1.0.
I can see 10 crashes in 24 hours due to this issue. The new version is installed by 434 users. Most users are not heavy users, so I think these numbers are quite disturbing.

image

@MikeHillberg
Copy link
Contributor

Adding @ranjeshj.

@wbokkers
Copy link
Author

wbokkers commented Jan 17, 2022

@MikeHillberg @ranjeshj
I see this issue happening for all kind of scroll areas (e.g ScrollViewer). Not only ListViews and not only those that has ItemsUpdatingScrollMode set.
For some sizes, scrolling to the end (using the touchpad) just crashes due to a layout cycle.

@wbokkers
Copy link
Author

wbokkers commented Jan 17, 2022

You can see the crash happen for this simple XAML:

  <ScrollViewer
      Margin="12,8"
      Height="427.2">
      <StackPanel>
          <Border Margin="8" Height="192" Background="Green" Width="40"/>
          <Border Margin="8" Height="192"  Background="Blue" Width="40"/>
          <Border Margin="8" Background="Yellow" Height="30" Width="40"/>
      </StackPanel>
  </ScrollViewer>

Note the specified Height! The content of the scroll viewer is very simple. It looks like the crash is related to the content height AND the scroll viewer height.

@RBrid
Copy link
Contributor

RBrid commented Jan 17, 2022

@wbokkers, thank you very much for the information you provided. This looks very much like a bug I have been investigating recently. That one depends on the Scale factor used on the machine, 100%, 125%, 150%, 175%, 200%, etc... It needed 175% to repro.

I tried all the Scale factors, but I could not repro the crash with the simple ScrollViewer markup above. What scale factor are you using on your machine to repro? Thank you.

@wbokkers
Copy link
Author

wbokkers commented Jan 17, 2022

@RBrid My scale factor is 125% with a 1920x1080 resoltion. That is works with a different scale factor does not surprise me. The issue is very much dependent on the height of the scroll area and the contents, and changing the scale will change the sizes of the scroll area and the contents.

@wbokkers
Copy link
Author

The scale factor setting is probably why I don't see this issue occurring for all of our users.

@wbokkers
Copy link
Author

Changing the scale factor with only 1% will 'solve' the ScrollViewer-example on my machine. But I am not convinced that this will solve all situations.

@wbokkers
Copy link
Author

The XAML Controls Gallery app also crashes on some listviews when scrolling to the end of the list on my machine. This is probably the same issue:
xamlcontrolsgallery://item/NavigationView

@RBrid
Copy link
Contributor

RBrid commented Jan 18, 2022

Thank you @wbokkers, I can repro the crash now. The reason why I did not repro earlier is because I was using a plain UWP app. I needed to make use of WinUI 2.7 which changed the control template of the ScrollViewer by adding a 1px padding around its 2 ScrollBars.

@LucaCris
Copy link

LucaCris commented Mar 5, 2023

I had the same layout cycle issue in a XAML island control within a Win32 app using WinUI 2.8.2 when zoom is enabled on the Scrollviewer. When using a zoom factor greater than 4.0 scrolling to the bottom is triggering the layout cycle.

Removing the 1px margin around the scrollbar seems to fix the issue.

<UserControl.Resources>
  <Thickness x:Key="ScrollViewerScrollBarMargin">0</Thickness>
</UserControl.Resources>

Upgrade to 3.0 then retry. :)

@Reza-Noei
Copy link

Reza-Noei commented Jul 20, 2023

I had similar problem with my UserControl in WinUI3
I have binded an Slider to a TextBox in TwoWay mode.

TargetFramework: net6.0-windows10.0.19041.0
Microsoft.WindowsAppSDK: 1.3.230602002
OS Edition: Windows 11 Pro
Version: 22H2
OS build: 22621.1992
Experience: Windows Feature Experience Pack 1000.22644.1000.0

<UserControl
    x:Class="BSN.Kava.UI.SDK.UserControls.DecoratedSlider"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:converters="using:BSN.Kava.UI.SDK.Converters"
    Name="decoratedSlider"
    mc:Ignorable="d">
    <UserControl.Resources>
        <converters:DoubleStringConverter x:Key="DoubleStringConverter" />
    </UserControl.Resources>
    <StackPanel>
        <TextBlock Margin="0 0 0 8"
                   FontWeight="Normal" 
                   Text="{Binding Title, ElementName=decoratedSlider}"/>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="auto"/>
            </Grid.ColumnDefinitions>

            <Slider x:Name="Slider" 
                    Grid.Column="0"
                    Margin="0 0 18 0"
                    Padding="0 6 0 6"
                    Value="{Binding ElementName=decoratedSlider, Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                    Minimum="{Binding ElementName=decoratedSlider, Path=Minimum, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                    Maximum="{Binding ElementName=decoratedSlider, Path=Maximum, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                    VerticalAlignment="Bottom">
            </Slider>

            <StackPanel Grid.Column="1" >
                <TextBox Width="80" 
                         TextAlignment="Center"
                         KeyDown="SliderTextBox_KeyDown"
                         LostFocus="SliderTextBox_LostFocus"
                         Text="{Binding ElementName=Slider, Path=Value, Mode=TwoWay, Converter={StaticResource DoubleStringConverter}}"></TextBox>
            </StackPanel>
        </Grid>
    </StackPanel>
</UserControl>

And here is my complete code-behind:

public sealed partial class DecoratedSlider : UserControl
{
    public DecoratedSlider()
    {
        this.InitializeComponent();
    }

    public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(DecoratedSlider), new PropertyMetadata("Decorated Slider"));

    public string Title
    {
        get => (string)GetValue(TitleProperty);
        set => SetValue(TitleProperty, value);
    }

    public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register(nameof(Minimum), typeof(double), typeof(DecoratedSlider), new PropertyMetadata(100.0));

    public double Minimum
    {
        get => (double)GetValue(MinimumProperty);
        set => SetValue(MinimumProperty, value);
    }

    public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register(nameof(Maximum), typeof(double), typeof(DecoratedSlider), new PropertyMetadata(500.0));

    public double Maximum
    {
        get => (double)GetValue(MaximumProperty);
        set => SetValue(MaximumProperty, value);
    }

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(double), typeof(DecoratedSlider), new PropertyMetadata(300.0));

    public double Value
    {
        get => (double)GetValue(ValueProperty);
        set => SetValue(ValueProperty, value);
    }

    private void SliderTextBox_KeyDown(object sender, KeyRoutedEventArgs e)
    {
        if (e.Key == Windows.System.VirtualKey.Enter)
        {
            if (double.TryParse((sender as TextBox).Text, out _) == false)
                (sender as TextBox).Text = Slider.Value.ToString();

            Slider.Focus(FocusState.Keyboard);
        }
    }

    private void SliderTextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        if (double.TryParse((sender as TextBox).Text, out _) == false)
            (sender as TextBox).Text = Slider.Value.ToString();
    }
}

and here is my ValueConverter:

public class DoubleStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return value.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        double doubleValue;

        if (double.TryParse(value.ToString(), out doubleValue) == false)
            return 0;
        
        return doubleValue;
    }
}

@soroshsabz
Copy link

soroshsabz commented Jul 20, 2023

@Reza-Noei Please add your SDK version and Windows version

Are you using WinUI 3 or 2?

@Reza-Noei
Copy link

Reza-Noei commented Jul 20, 2023

@Reza-Noei Please add your SDK version and Windows version

Are you using WinUI 3 or 2?

I have updated my case, I added more info

@soroshsabz

@soroshsabz
Copy link

@bpulliam any update for this issue exists from Microsoft? I think crash bug must have high priority from Developer teams

@soroshsabz
Copy link

I had similar problem with my UserControl in WinUI3 I have binded an Slider to a TextBox in TwoWay mode.

TargetFramework: net6.0-windows10.0.19041.0 Microsoft.WindowsAppSDK: 1.3.230602002 OS Edition: Windows 11 Pro Version: 22H2 OS build: 22621.1992 Experience: Windows Feature Experience Pack 1000.22644.1000.0

<UserControl
    x:Class="BSN.Kava.UI.SDK.UserControls.DecoratedSlider"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:converters="using:BSN.Kava.UI.SDK.Converters"
    Name="decoratedSlider"
    mc:Ignorable="d">
    <UserControl.Resources>
        <converters:DoubleStringConverter x:Key="DoubleStringConverter" />
    </UserControl.Resources>
    <StackPanel>
        <TextBlock Margin="0 0 0 8"
                   FontWeight="Normal" 
                   Text="{Binding Title, ElementName=decoratedSlider}"/>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="auto"/>
            </Grid.ColumnDefinitions>

            <Slider x:Name="Slider" 
                    Grid.Column="0"
                    Margin="0 0 18 0"
                    Padding="0 6 0 6"
                    Value="{Binding ElementName=decoratedSlider, Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                    Minimum="{Binding ElementName=decoratedSlider, Path=Minimum, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                    Maximum="{Binding ElementName=decoratedSlider, Path=Maximum, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                    VerticalAlignment="Bottom">
            </Slider>

            <StackPanel Grid.Column="1" >
                <TextBox Width="80" 
                         TextAlignment="Center"
                         KeyDown="SliderTextBox_KeyDown"
                         LostFocus="SliderTextBox_LostFocus"
                         Text="{Binding ElementName=Slider, Path=Value, Mode=TwoWay, Converter={StaticResource DoubleStringConverter}}"></TextBox>
            </StackPanel>
        </Grid>
    </StackPanel>
</UserControl>

And here is my complete code-behind:

public sealed partial class DecoratedSlider : UserControl
{
    public DecoratedSlider()
    {
        this.InitializeComponent();
    }

    public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(DecoratedSlider), new PropertyMetadata("Decorated Slider"));

    public string Title
    {
        get => (string)GetValue(TitleProperty);
        set => SetValue(TitleProperty, value);
    }

    public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register(nameof(Minimum), typeof(double), typeof(DecoratedSlider), new PropertyMetadata(100.0));

    public double Minimum
    {
        get => (double)GetValue(MinimumProperty);
        set => SetValue(MinimumProperty, value);
    }

    public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register(nameof(Maximum), typeof(double), typeof(DecoratedSlider), new PropertyMetadata(500.0));

    public double Maximum
    {
        get => (double)GetValue(MaximumProperty);
        set => SetValue(MaximumProperty, value);
    }

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(double), typeof(DecoratedSlider), new PropertyMetadata(300.0));

    public double Value
    {
        get => (double)GetValue(ValueProperty);
        set => SetValue(ValueProperty, value);
    }

    private void SliderTextBox_KeyDown(object sender, KeyRoutedEventArgs e)
    {
        if (e.Key == Windows.System.VirtualKey.Enter)
        {
            if (double.TryParse((sender as TextBox).Text, out _) == false)
                (sender as TextBox).Text = Slider.Value.ToString();

            Slider.Focus(FocusState.Keyboard);
        }
    }

    private void SliderTextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        if (double.TryParse((sender as TextBox).Text, out _) == false)
            (sender as TextBox).Text = Slider.Value.ToString();
    }
}

and here is my ValueConverter:

public class DoubleStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return value.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        double doubleValue;

        if (double.TryParse(value.ToString(), out doubleValue) == false)
            return 0;
        
        return doubleValue;
    }
}

@marb2000 please see @Reza-Noei example for better diagnosis

@duncanmacmichael duncanmacmichael added the bug Something isn't working label Oct 31, 2023
@codendone codendone added this to the WinAppSDK 1.5 milestone Nov 16, 2023
@codendone codendone added the fixed-internally This bug has been fixed, and the fix will be shipped in the next version of WinUI 3. label Nov 16, 2023
@codendone
Copy link
Contributor

A fix for this issue has just been completed for 1.5. Fixes in CFrameworkElement::MeasureCore and CFrameworkElement::ArrangeCore were necessary in order to ensure consistent results without sizing larger than the available space.

@christosk92
Copy link

@codendone I updated to 1.5 experimental, but I still see it occur sometimes. Was it expected to be fixed in 1.5 exp-1 ? Or is it schedule for a future release?

Thanks!

@microsoft-github-policy-service microsoft-github-policy-service bot added the needs-triage Issue needs to be triaged by the area owners label Dec 7, 2023
@christosk92
Copy link

christosk92 commented Dec 7, 2023

Desktop.2023.12.07.-.17.34.01.01.mp4

I have attached a video showcasing that it occurs with just a basic ItemsRepeater, that is incrementally loaded based on scroll position.

ItemsRepeater.Layout:

<UniformGridLayout
    ItemsJustification="Start"
    ItemsStretch="Uniform"
    MinColumnSpacing="6"
    MinItemHeight="270"
    MinItemWidth="200"
    MinRowSpacing="12"
    Orientation="Horizontal" />

@wbokkers
Copy link
Author

wbokkers commented Dec 7, 2023

It seems to be more frequent in 1.4.3/ But it only affects 0.02% of our users.

@christosk92
Copy link

christosk92 commented Dec 7, 2023

@wbokkers It seems that my specific case is caused by the incremental loading mechanism of my app.
If I load all the entities in at once, it never throws the exception; but this is sub-optimal at best since there can be so many entities.

I hook into the "ViewChanged" event of a ScrollView. it seems that this may cause an infinite layout cycle.

Has anyone else figured out a better way of incrementally loading ItemsRepeater?

P.S: The incrementalloadingcollection does not work with ItemsRepeater.

@bpulliam bpulliam removed the needs-triage Issue needs to be triaged by the area owners label Dec 11, 2023
@jinzaz
Copy link

jinzaz commented Feb 23, 2024

@christosk92 i was use ItemsRepeater.EffectiveViewportChanged event to solve this question, determine EffectiveViewportChangedEventArgs.EffectiveViewport Point Is it close to ItemsRepeater‘s bottom Point.
I'm not sure if I can solve your problem.

@microsoft-github-policy-service microsoft-github-policy-service bot added the needs-triage Issue needs to be triaged by the area owners label Feb 23, 2024
@bpulliam bpulliam removed needs-triage Issue needs to be triaged by the area owners fixed-internally This bug has been fixed, and the fix will be shipped in the next version of WinUI 3. labels Feb 29, 2024
@kaismic
Copy link

kaismic commented May 24, 2024

@codendone Hi I'm just wondering if the fix has already been released or not yet? I'm using WindowsAppSDK 1.5.240428000 but still have the same issue.

@microsoft-github-policy-service microsoft-github-policy-service bot added the needs-triage Issue needs to be triaged by the area owners label May 24, 2024
@kaismic
Copy link

kaismic commented May 26, 2024

@codendone Hi I'm just wondering if the fix has already been released or not yet? I'm using WindowsAppSDK 1.5.240428000 but still have the same issue.

Actually I tried using ScrollViewer instead of ScrollView and now it works without problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-Lists ListView, GridView, ListBox, etc area-Scrolling bug Something isn't working Crash whenever user reports a crash or app freeze needs-triage Issue needs to be triaged by the area owners product-winui3 WinUI 3 issues Regression team-Controls Issue for the Controls team
Projects
None yet
Development

No branches or pull requests