InvalidOperationException при добавлении элементов в выпадающий список в событии - PullRequest
0 голосов
/ 28 апреля 2019

Я делаю довольно простой селектор базы данных / таблицы SQL Server в WPF и, подобно вкладке «Свойства соединения» SSMS (при нажатии кнопки «Параметры»), хочу элемент в поле со списком, который будет подключаться ксервера, найдите список баз данных или таблиц (в зависимости от того, какой комбобокс активен) и заполните этот список ниже таблицей разделителей этими базами данных / таблицами.Когда я запускаю свой проект, чтобы сделать это, я получаю InvalidOperationException, заявляя, что «Коллекция была изменена;операция перечисления может не выполняться. 'в строке ShowDialog формы, а не в самой форме.

Я завернул свой код события в блок Try / Catch, чтобы попытаться лучше понять, откуда выдается исключение, но оно никогда не перехватываетв моем собственном коде.Исключение выдается только после завершения моего события, где-то между событием и бэкэндом 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) 

Исключение говорит о том, чтоисточник просто "mscorlib"

Рассматриваемое событие выглядит так:

        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.");
            }
        }

Я ожидал, что это сработает, но вместо этого я получаю исключение. Широкий "catch (Исключение ex) "никогда не выполняется, что указывает на то, что это проблема, вызванная тем, что WPF делает в фоновом режиме.Я подозреваю, что это возможно из-за того, что это событие вызвано выбором опции в расширенном комбинированном списке, но этот тип поведения работает в SSMS, поэтому я не уверен, что делаю неправильно.Я видел, что эта проблема часто возникает при изменении перечисления в цикле foreach, но я не использовал ни одного из них в этом событии или где-либо еще в этом проекте.

Ответы [ 2 ]

1 голос
/ 30 апреля 2019

Вы, кажется, обрабатываете событие Selected для ComboBoxItem. Попробуйте обработать событие SelectionChanged для ComboBox. Тогда вы не должны получить InvalidOperationException.

0 голосов
/ 29 апреля 2019

Вы делаете

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

Здесь вы изменяете объект коллекции в цикле while. И я не вижу инициализации cbxDatabase в вашем коде, вставленном выше. Может быть, это причина исключения.

...