Ах, аккуратно. Это показывает, что я в главной теме
ожусь в процессе добавления новой функциональности к моим элементам управления winforms, и часть этого требует, чтобы переменная, которая когда-то всегда использовалась, теперь является необязательной (если она нулевая, получите данные из второго источника). Я внес некоторые изменения и запустил свою форму, только чтобы узнать, что ничего не происходит, даже функциональность, которая раньше работала. В замешательстве я прошел по коду и обнаружил, что мой пользовательский элемент управления Winforms выбрасываетNullReferenceException
когда он встретил мою переменную, но в интерфейсе не было выдано никаких ошибок.
Моя установка у меня естьUserControl
со списком. Когда пользователь меняет это поле со списком, он загружает вторичныйUserControl
в панели первый элемент управления. Второй элемент управления - это то, что вызывает исключение.
Вот пути к коду:
private void cmbActionType_SelectedIndexChanged(object sender, EventArgs e)
{
if (_loading)
return;
// ActionType was changed, update the action.ActionType value
if (cmbActionType.SelectedItem != null)
{
if (cmbActionType.SelectedItem.ToString() == SETVALUE_OPTION)
_action.ActionType = ActionTypes.SetValue;
else if (cmbActionType.SelectedItem.ToString() == CHECKVALUE_OPTION)
_action.ActionType = ActionTypes.CheckValue;
else
_action.ActionType = ActionTypes.CustomAction;
}
RefreshActionPanel();
_editor.DataModified();
}
private void RefreshActionPanel()
{
// Control defaults
AnchorStyles styles = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
UserControl subControl = null;
// Clear the currently active control
pnlActionDetails.Controls.Clear();
// Determine what type of control to load in the panel
if (cmbActionType.SelectedItem != null && cmbCaseType.SelectedItem != null)
{
// SetValue or CheckValue actions
if (cmbActionType.SelectedItem.ToString() == CHECKVALUE_OPTION || cmbActionType.SelectedItem.ToString() == SETVALUE_OPTION)
{
if (_caseTypeMap.ContainsKey(cmbCaseType.SelectedItem.ToString()))
subControl = new SetCheckActionControl(_action, _editor, _caseTypeMap[cmbCaseType.SelectedItem.ToString()]);
}
// CustomAction action type
else
{
// Check if the requested case is a type or defined in a script
if (_caseTypeMap.ContainsKey(cmbCaseType.SelectedItem.ToString()))
{
subControl = new CustomActionControl(_action, _editor, _caseTypeMap[cmbCaseType.SelectedItem.ToString()]);
}
else if (_editor.ScriptDefinitions.Any(x => x.CaseName == cmbCaseType.SelectedItem.ToString()))
{
var definitions = _editor.ScriptDefinitions.Where(x => x.CaseName == cmbCaseType.SelectedItem.ToString()).ToList();
subControl = new CustomActionControl(_action, _editor, definitions);
}
}
}
if (subControl != null)
{
subControl.Anchor = styles;
subControl.Height = pnlActionDetails.Height;
subControl.Width = pnlActionDetails.Width;
pnlActionDetails.Controls.Add(subControl);
}
}
public CustomActionControl(TestAction action, fmEditor editor, IList<TcScriptDefinition> scriptDefinitions) : base(action, editor)
{
_loading = true;
InitializeComponent();
_scriptDefinitions = scriptDefinitions;
PopulateActionList();
SetupDataGrid();
_loading = false;
}
private void SetupDataGrid()
{
// Clear the current contents of the datagrid
grdParameters.Rows.Clear();
if (cmbAction.SelectedItem == null)
return;
// Retrieve the action code from the drop down
string actionCode = cmbAction.SelectedValue.ToString();
// Check if any paramters are available for this action
if (!_availableActionParameters.ContainsKey(actionCode))
return;
// Add a new row for each parameter available for this action
foreach (string param in _availableActionParameters[actionCode])
{
string display = param;
// Determine if the parameter has a display string
if (_formInstance.CodeDisplayMap.ContainsCode(param))
display = _formInstance.CodeDisplayMap.GetDisplayStringFromCode(param);
// Create the array for the row, with an empty string as the current value
string[] row = { display, string.Empty };
// Check if the current action uses this action code.
// If so, retrieve the value for this parameter and use it in the row
// Note: Case-INsensitive comparison must be performed here
if (_action.Attributes["action"].Equals(actionCode, StringComparison.CurrentCultureIgnoreCase))
if (_action.Attributes.ContainsKey(param))
row[1] = _action.Attributes[param];
grdParameters.Rows.Add(row);
}
}
NullReferenceException
исходит отSetupDataGrid()
метод где_formInstance
называется Тем не менее, обычно, когда приложение встречает необработанное исключение, система JIT выдает сообщение об ошибке, говорящее о таком (и, как вы можете видеть, нетtry/catch
заявления используются, если я не слепой).
Почему в моем приложении winforms отсутствуют признаки возникновения исключений. Я предпочел бы, чтобы происходило необработанное сообщение об исключении, а не происходило ничего, поскольку пользователям было бы труднее узнать, что что-то критичное пошло не так (в отличие от того, что оно не отвечает на их команды)
Редактировать: Чтобы прояснить это, поскольку кажется, что есть некоторая путаница, я НЕ забочусь о нарушении этого исключения в визуальной студии при отладке. Дело в том, что приложение не должно скрывать необработанные исключения, и мое приложение должно аварийно завершить работу (или, скорее, показать сообщение JIT о том, что произошло необработанное исключение), даже если оно не находится в режиме отладки за пределами Visual Studio.Это не вопрос времени отладки, а вопрос времени выполнения. Если этот код бросаетOutOfMemoryException
например, мне нужно, чтобы это не было тихо проигнорировано. Прямо сейчас это игнорируется.