DataGridCheckBoxColumn的用法-引发未处理的异常

时间:2020-05-22 12:07:24

标签: c# xaml datagrid avaloniaui avalonia

在DataGrid中使用DataGridCheckBoxColumn并将其绑定到支持模型中的布尔属性时,会发生这种情况。单击该列并选中/未选中复选框时,它的行为符合预期。但是,当我关闭主窗口时,将引发异常。仅使用文本列并与之交互时不会发生这种情况。如果我根本不与复选框列交互,而只是关闭窗口,也不会发生这种情况。只有在与复选框列进行交互之后关闭窗口时,才会发生这种情况。

开发环境:

操作系统:
1. Arch Linux,Gnome 3和Wayland。
2. Windows 10专业版

开发:
dotnet核心3.1.103
IDE:VS代码

复制步骤:

使用DataGrid的常规过程是本教程文章中提到的: Avalonia DataGrid Getting Started

我对本文所做的唯一更改是将DataGridCheckBoxColumn添加到DataGrid,并将布尔IsChecked布尔属性添加到本教程中使用的“ Person”模型类中-然后将两者绑定在一起。

因此关键步骤是:

  1. $ dotnet new avalonia.mvvm
  2. 在* csproj文件中,将所有Avalonia包含的版本都替换为0.9.10,因为那是我正在使用的DataGrid的版本。
  3. $ dotnet add package Avalonia.Controls.DataGrid
  4. 在App.xaml中,添加样式:
    <StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Default.xaml"/>
  5. 将以下属性添加到模型类“ Person” ---其余代码保持不变,并按照链接的教程进行操作:
 public bool IsChecked
        {get;set;}
  1. 将DataGridCheckBoxColumn添加到DataGrid并按如下所示进行绑定(其余的列保持不变,并按照链接的教程进行操作):
<DataGrid.Columns>
        <DataGridTextColumn Header="First Name" 
                            Binding="{Binding FirstName}" 
                            Width="2*" />
        <DataGridTextColumn Header="Last Name" 
                            Binding="{Binding LastName}" 
                            Width="2*" />
        <DataGridTextColumn Header="Department" 
                            Binding="{Binding DepartmentNumber}" 
                            Width="*" />

        <DataGridCheckBoxColumn Header="IsChecked" 
                            Binding="{Binding IsChecked}" 
                            Width="*" />

    </DataGrid.Columns>
  1. 然后,当我运行应用程序(从命令行或vscode)时-GUI按预期显示-带有所有列和值-并通常显示其他复选框列。 __ 当我单击复选框列时-复选框确实按预期方式被选中和取消选中(尽管需要额外单击一次)。 但是当我通过单击右上角的“ X”关闭窗口时-那是未处理的异常发生的时间-不在此之前。

完整的例外文本:

未处理的异常。 System.InvalidOperationException:集合已被修改;枚举操作可能无法执行。 在System.Collections.Generic.List`1.Enumerator.MoveNextRare()处 在Avalonia.Collections.AvaloniaList`1.Enumerator.MoveNext() 在System.Linq.Enumerable.OfTypeIterator [TResult](IEnumerable源)+ MoveNext() 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Visual.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Input.InputElement.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.Control.OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e) 在Avalonia.Controls.TopLevel.HandleClosed() 在Avalonia.Controls.WindowBase.HandleClosed() 在Avalonia.Controls.Window.HandleClosed() 在Avalonia.X11.X11Window.Cleanup() 在Avalonia.X11.X11Window.Dispose() 在Avalonia.X11.X11Window.OnEventSync(XEvent ev) 在Avalonia.X11.X11Window.OnEvent(XEvent ev) 在Avalonia.X11.X11PlatformThreading.HandleX11(CancellationToken cancelleToken) 在Avalonia.X11.X11PlatformThreading.RunLoop(CancellationToken cancelleToken) 在Avalonia.Threading.Dispatcher.MainLoop(CancellationToken cancelleToken) 在Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.Start(String [] args) 在Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime [T](T builder,String [] args,ShutdownMode shutdownMode) 在/home/[myusername]/[pathtoproject]/Program.cs:line 14中的d3.Program.Main(String [] args)

Person类的代码:

public class Person
    {
        public int DepartmentNumber { get; set; }

        public string DeskLocation{ get; set; }

        public int EmployeeNumber { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public bool IsChecked
        {get;set;}
    }

MainWindowViewModel的代码,充当MainWindow的代码,并使用上面的Person类托管ObservableCollection并将其公开为名为People的公共属性。 DataGrid绑定到此People属性,该属性用作Person类的集合(其属性由不同的列表示,例如DataGridTextColumn和DataGridCheckBoxColumn):

public class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<Person> People { get; set;}

        public MainWindowViewModel()
        {
            People = new ObservableCollection<Person>(GenerateMockPeopleTable());
        }

        private ObservableCollection<Person> GenerateMockPeopleTable()
        {
            var defaultPeople = new ObservableCollection<Person>()
            {
                new Person()
                {
                    FirstName = "Pat", 
                    LastName = "Patterson", 
                    EmployeeNumber = 1010,
                    DepartmentNumber = 100, 
                    DeskLocation = "B3F3R5T7",
                    IsChecked = false
                },
                new Person()
                {
                    FirstName = "Jean", 
                    LastName = "Jones", 
                    EmployeeNumber = 973,
                    DepartmentNumber = 200, 
                    DeskLocation = "B1F1R2T3",
                    IsChecked = true
                },
                new Person()
                {
                    FirstName = "Terry", 
                    LastName = "Tompson", 
                    EmployeeNumber = 300,
                    DepartmentNumber = 100, 
                    DeskLocation = "B3F2R10T1",
                    IsChecked = false
                }
            };

            return defaultPeople;
        }
    }

更新:我已放弃寻找解决方案。这是我的解决方法:

而不是使用DataGridCheckBoxColumn(它也具有仅在单击两次时才被检查的额外烦恼-我正在使用DataGridTemplateColumn。它解决了上面的异常问题-以及我希望的属性可以在单击。

<DataGridTemplateColumn Header="Select Todo">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding IsChecked}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

2 个答案:

答案 0 :(得分:0)

我认为您的问题与所使用的收藏有关,而不是复选框。 您必须在收集后致电.ToList()。 请检查以下链接: Collection was modified; enumeration operation may not execute

答案 1 :(得分:0)

GenerateMockPeopleTable()替换为GenerateMockPeopleTable().ToList(),然后检查问题是否解决。