简体   繁体   中英

UWP XAML is throwing an unhandled exception when a collection is empty

I have two ObservableCollection<T> and its bonded with two different ListView UI.

ObservableCollection<Department> deptList = new ObservableCollection<Department>();

ObservableCollection<Teacher> teacherList = new ObservableCollection<Teacher>();

User can add or remove items from the collection in the run time.

At some point, if either of the lists is empty, the app freezes and throws an unhandled exception {Windows.UI.Xaml.UnhandledExceptionEventArgs}

#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
            UnhandledException += (sender, e) =>
            {
                if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
            };
#endif

Exception Message

Message = "Layout cycle detected. Layout could not complete.\\r\\nLayout cycle detected. Layout could not complete."

_message = "A cycle occurred while laying out the GUI."

Here is the code block for ListView UI -

<ListView Header="Department List"
    x:Name="depertmentList"
    ItemsSource="{x:Bind deptList}"
    SelectionMode="Multiple"
    SelectionChanged="depertmentList_SelectionChanged">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="data:Department">
                <StackPanel Margin="1">
                    <TextBlock Text="{x:Bind Dept}" Margin="1"/>
                    <TextBlock Text="{x:Bind SemesterCount}" Margin="1"/>
                    <TextBlock Text = "{Binding Courses, Converter={StaticResource ListToStringConverter}}"/>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
<ListView Header="Teacher List"
    x:Name="teacherListView"
    ItemsSource="{x:Bind teacherList}"
    SelectionMode="Single"
    SelectionChanged="teacherListView_SelectionChanged"
    Margin="2">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="data:Teacher">
            <StackPanel>
                <TextBlock Text="{x:Bind Name}"/>
                <TextBlock Text="{x:Bind Designation}" Margin="1"/>
                <TextBlock Text="{x:Bind Dept}" Margin="1"/>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

C# code for events

        private void depertmentList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            
            if (depertmentList.SelectedItem == null)
            {
                removeDept.IsEnabled = false;
                teacherListView.ItemsSource = teacherList;
            }
            else
            {
                removeDept.IsEnabled = true;
                ObservableCollection<Department> t = new ObservableCollection<Department>();
                Department temp = (Department)depertmentList.SelectedItem;
                teacherListView.ItemsSource = from teacher in teacherList
                                              where teacher.Dept == temp.Dept
                                              select teacher;
            }
        }
        private void teacherListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (teacherListView.SelectedItem == null)
            {
                removeTeacher.IsEnabled = false;
            }
            else
            {
                removeTeacher.IsEnabled = true;
            }
        }

Point to be noted, Teacher class derives from Department class. And if I remove a Department, all the teacher associated with that department gets removed too.

To prevent crashing the app, I had to add a hardcoded garbage item to the list which the user can remove later in run time.

And again if one of the lists is empty, the app crashes. But if there is at least one item in both lists, nothing happens.

Now, my question is How can I resolve this issue without adding any type of garbage item? I want to prevent crashing even if the lists are empty or null.

It seems like an inner layout design. The problem is ScrollViewer to cause loop rendering. You can set a Height to your scrollViewer. For example:

<ScrollViewer Margin="2" RelativePanel.Below="TeacherFilter" Height="100">

or as the link @Noorul shared to set the VerticalScrollBarVisibility as Auto.

<ScrollViewer Margin="2" RelativePanel.Below="TeacherFilter" VerticalScrollBarVisibility="Auto">

The error you are getting is a bit obscure. Your problem, while not exactly possible to debug without setting calm and c# is a variation of this.

When one or the other of your lists is empty, then some kind of exception occurs. Do you have any linq query that assumes that something will return? Do you access that something after all?

The problem is just saying that UWP is trying in an infinite loop to reconstruct your UI, something bad happens and it retries. That is why your application crashed. Because of the infinite loop.

If you used a scrollviewer inside your ListView , or you may iterate through your items, when there is no item in list.

This threads discus about same issue.

Layout cycle detected, layout could not complete

Layout cycle detected. Layout could not complete. Layout cycle detected. Layout could not complete

Hope this helps.

If you post your xaml code, it will be usefull the diagnose your issue.

Thankyou.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM