简体   繁体   English

在事件中将项目添加到组合框时发生InvalidOperationException

[英]InvalidOperationException when adding items to a combobox in an event

I'm making a fairly simple SQL Server Database/Table selector in WPF, and, similar to SSMS' "Connection Properties" tab (when clicking the Options button), want an item in a combo box that will connect to the server, find a list of databases or tables (depending on which combobox is active), and populate the combobox below a separator line with these databases/tables. 我正在WPF中制作一个相当简单的SQL Server数据库/表选择器,并且类似于SSMS的“连接属性”选项卡(单击“选项”按钮时),想要组合框中的一项将连接到服务器,找到数据库或表的列表(取决于哪个组合框处于活动状态),并用这些数据库/表填充分隔线下方的组合框。 When I run my project to do this, I get an InvalidOperationException stating 'Collection was modified; 当我运行项目来执行此操作时,我收到一个InvalidOperationException声明“集合已修改; enumeration operation may not execute.' 枚举操作可能无法执行。” on the ShowDialog line of the form, not within the form itself. 在窗体的ShowDialog行上,而不是在窗体本身内。

I've wrapped my event code in a Try/Catch block to try and better understand where the exception is being thrown from, but it never catches in my own code. 我已将事件代码包装在Try / Catch块中,以尝试并更好地了解从何处引发异常,但该事件从未捕获到我自己的代码中。 The exception is only thrown after my event exits, somewhere between the event and the WPF backend, with the following Stack Trace (entries before the application actually starts up have been removed): 仅在事件退出后,事件与WPF后端之间的某个位置以及以下堆栈跟踪(在应用程序实际启动之前的条目已被删除)之后才引发异常:

   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at System.Collections.Generic.List`1.Enumerator.MoveNext()
   at System.Windows.Controls.Primitives.Selector.SelectionChanger.CreateDeltaSelectionChange(List`1 unselectedItems, List`1 selectedItems)
   at System.Windows.Controls.Primitives.Selector.SelectionChanger.End()
   at System.Windows.Controls.Primitives.Selector.SelectionChanger.SelectJustThisItem(ItemInfo info, Boolean assumeInItemsCollection)
   at System.Windows.Controls.ComboBox.NotifyComboBoxItemMouseUp(ComboBoxItem comboBoxItem)
   at System.Windows.Controls.ComboBoxItem.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Window.ShowHelper(Object booleanBox)
   at System.Windows.Window.Show()
   at System.Windows.Window.ShowDialog()
   at VDBFImport.App.Application_Startup(Object sender, StartupEventArgs e) 

The exception says that the source is simply "mscorlib" 唯一的例外是来源是“ mscorlib”

The event in question looks like this: 有问题的事件如下所示:

        private void CbiBrowseDB_Selected(object sender, RoutedEventArgs e) {
            try {
                using(SqlConnection conn = new SqlConnection(GetConnectionString())) {
                    try {
                        conn.Open();
                    } catch(Exception ex) {
                        MessageBox.Show("Failed to connect to the SQL Server: " + ex.Message);
                        return;
                    }

                    DataTable dbs = new DataTable();
                    SqlDataAdapter adapter = new SqlDataAdapter("SELECT [name] FROM sys.databases WHERE [name] NOT IN ('master', 'tempdb', 'model', 'msdb')", conn);
                    try {
                        adapter.Fill(dbs);
                    } catch(InvalidOperationException ex) {
                        MessageBox.Show("Failed to retrieve table list from the SQL Server: " + ex.Message);
                    }

                    try {
                        while(cbxDatabase.Items.Count > 2) {
                            cbxDatabase.Items.RemoveAt(cbxDatabase.Items.Count - 1);
                        }
                        for(int i = 0; i < dbs.Rows.Count; ++i) {
                            ComboBoxItem item = new ComboBoxItem();
                            item.Content = dbs.Rows[i].Field<string>("name");
                            cbxDatabase.Items.Add(item);
                        }
                        cbxDatabase.Items.Refresh();
                    } catch(InvalidOperationException ex) {
                        MessageBox.Show("Failed to update the list of databases: " + ex.Message + "\r\n" + ex.StackTrace);
                    }
                }
            } catch (Exception ex) {
                MessageBox.Show("Failed.");
            }
        }

I expected this to just work, but instead I get the exception thrown.The broad "catch (Exception ex)" never executes, which indicates to me that this is an issue caused by something WPF is doing in the background. 我希望这能正常工作,但会引发异常。宽泛的“ catch(ex ex ex)”永远不会执行,这向我表明这是WPF在后台执行的操作引起的问题。 I suspect it may be possible that it's due to the fact that this event is triggered by selecting an option in the expanded combobox, but this type of behavior works in SSMS, so I'm not sure what I'm doing wrong. 我怀疑这可能是由于在扩展的组合框中选择一个选项而触发了此事件,但是这种类型的行为在SSMS中有效,因此我不确定自己在做什么错。 I've seen that this issue often occurs when modifying an enumeration in a foreach loop, but I have not used any of those in this event, or anywhere else in this project. 我已经看到,在foreach循环中修改枚举时,经常会出现此问题,但是在此事件或项目中的其他任何地方,我都没有使用过任何枚举。

You seem to handle the Selected event for the ComboBoxItem . 您似乎可以处理ComboBoxItemSelected事件。 Try to handle the SelectionChanged event for the ComboBox instead. 尝试改为处理ComboBoxSelectionChanged事件。 Then you should get no InvalidOperationException . 然后,您应该不会收到InvalidOperationException

You are doing 你在做

while(cbxDatabase.Items.Count > 2) {
    cbxDatabase.Items.RemoveAt(cbxDatabase.Items.Count - 1);
}

Here you are modifying the collection object in the while loop. 在这里,您正在while循环中修改集合对象。 And I do not see cbxDatabase being initialized anywhere in your code pasted above. 而且我看不到cbxDatabase在上面粘贴的代码中的任何地方被初始化。 Maybe this is the cause of the exception. 也许这是导致异常的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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