NullReferenceException even when control is present in the previous page - c#

Whenever I try to retrieve the previous page dropdownlist control in bedCount() mwethod it gives this exception while I rest assure you that the control which I am searching is very much present in the previous page. What is the reason for this? My code is given below :
public partial class Room2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
DropDownList[] adult=new DropDownList[6];
DropDownList[] child = new DropDownList[6];
TableRow[] trp = new TableRow[5];
TableRow[] trc ={ trc1, trc2, trc3, trc4, trc5 };
DropDownList[] rtype ={ DropDownList1,DropDownList2, DropDownList3, DropDownList4, DropDownList5, DropDownList6 };
Label[] bed ={Label1,Label2,Label3,Label4,Label5,Label6};
int i,x,c=2;
for (i = 0; i < 5; i++)
{
trp[i] = (TableRow)PreviousPage.Master.FindControl("ContentPlaceHolder1").FindControl("tr" + (i + 1));
}
for (i = 0; i < 6; i++,c+=4)
{
adult[i] = (DropDownList)PreviousPage.Master.FindControl("ContentPlaceHolder1").FindControl("DropDownList" + c++);
child[i] = (DropDownList)PreviousPage.Master.FindControl("ContentPlaceHolder1").FindControl("DropDownList" + c);
}
for (i = 0; i < 6; i++)
{
x = adult[i].SelectedIndex + child[i].SelectedIndex;
switch (x)
{
case 0:
case 1:
rtype[i].Items.Add("Executive Class");
rtype[i].Items.Add("Business Class");
rtype[i].Items.Add("Gold Class (Type-I)");
rtype[i].Items.Add("Gold Class (Type-II)");
rtype[i].SelectedIndex = 0;
bed[i].Text = "No";
break;
case 2:
rtype[i].Items.Add("Business Class");
rtype[i].Items.Add("Gold Class (Type-I)");
rtype[i].Items.Add("Gold Class (Type-II)");
rtype[i].SelectedIndex = 0;
bed[i].Text = "1";
break;
case 3:
bed[i].Text = "1";
goto case 4;
case 4:
rtype[i].Items.Add("Gold Class (Type-I)");
rtype[i].Items.Add("Gold Class (Type-II)");
rtype[i].SelectedIndex = 0;
bed[i].Text = "2";
break;
case 5:
bed[i].Text = "2";
goto case 6;
case 6:
rtype[i].Items.Add("Gold Class (Type-II)");
rtype[i].SelectedIndex = 0;
bed[i].Text = "3";
break;
}
if (i<5 && trp[i].Visible)
trc[i].Visible = true;
}
}
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
if(DropDownList1.Items.Count<=3)
bedCount(DropDownList1,Label1,0);
}
protected void bedCount(DropDownList d,Label l,int a)
{
protected void bedCount(DropDownList d,Label l,int x)
{
DropDownList a=new DropDownList();
DropDownList c = new DropDownList();
int s;
a = (DropDownList)PreviousPage.Master.FindControl("ContentPlaceHolder1").FindControl("DropDownList"+x++);//gives exception here
c = (DropDownList)PreviousPage.Master.FindControl("ContentPlaceHolder1").FindControl("DropDownList"+x);
s = c.SelectedIndex + c.SelectedIndex;
if (d.SelectedItem.Equals("Business Class"))
if(s==2)
l.Text = "1";
else
l.Text = "No";
else if(d.SelectedItem.Equals("Gold Class (Type-I)"))
if(s==3)
l.Text = "1";
else if(s==4)
l.Text = "2";
else
l.Text = "No";
else if(d.SelectedItem.Equals("Gold Class (Type-II)"))
if(s==4)
l.Text = "1";
else if(s==5)
l.Text = "2";
else if(s==6)
l.Text = "3";
else
l.Text = "No";
}

When you change selected item in DropDownList1, then each item of your arrays
DropDownList[] adult=new DropDownList[6];
DropDownList[] child = new DropDownList[6];
will become a null because the page is recreated after each postback (even after changing dropdown list selected item)
On the first load of page you get your arrays filled because you fill them manually in Page_Load

Related

С# Form buttons do not update; when they are updated

Together with a friend, we are trying to create a sea battle for playing on a local network, we made a field of buttons, created islands on it, you can set up ships and move them. But when we connected the form to our server, after requesting the package, the form stops drawing buttons, they store the correct data, but their visual update does not occur
Here are the pieces of code
private void button1_Click(object sender, EventArgs e)
{
comboBox1.Visible = false;
comboBox2.Visible = false;
button1.Visible = false;
comboBox3.Visible = false;
button2.Visible = true;
SendPacket(PacketInfo.SendGameInfo);
Thread thread = new Thread(FightIsDone);
thread.Start();
State = GameState.Waiting;
}
void FightIsDone()
{
ReceivePacket();
this.Invoke(new Action(() => GameUpdate()));
}
public void GameUpdate()
{
Console.WriteLine("!");
State = GameState.Planing;
foreach (Ship ship in Ships)
{
ship.UseModuls();
}
SetShip(Ships);
UpdateSight();
Draw();
}
The problem is here, this method changes the image of the button or its color, it works fine until the packet is sent to the server, but after receiving it, only the information is updated, and the appearance of the form does not change
public void Draw()
{
foreach (CellButton Butt in Field)
{
if (Butt.Sigth)
{
Butt.Image = null;
SetImage(Butt);
}
else
{
Butt.BackColor = Color.Gray;
Butt.Image = null;
}
}
}
public void SetImage(CellButton Butt)
{
switch (Butt.Entety)
{
case GameObject.Water: Butt.BackColor = Color.DodgerBlue; break;
case GameObject.Island: Butt.Image = GetObjectImage(GameObject.Island); break;
case GameObject.Ship:
{
Butt.Image = Butt.modul.ModulImage;
break;
}
case GameObject.Torpedo: Butt.BackColor = Color.DarkBlue; break;
case GameObject.Fire: Butt.Image = GetObjectImage(GameObject.Fire); break;
}
}
static void SendPacket(PacketInfo info)
{
ms.Position = 0;
switch (info)
{
case PacketInfo.Connect:
writer.Write(0);
break;
case PacketInfo.SendCoordinate:
writer.Write(1);
formatter.Serialize(ms, new Coordinate(5, 0));
break;
case PacketInfo.LaunchSearch:
writer.Write(2);
writer.Write(Me.ID);
break;
case PacketInfo.SendGameInfo:
writer.Write(3);
writer.Write(Me.ID);
List<Ship> shpooks = new List<Ship>();
foreach (Ship s in Ships)
if (s.PlayerID == Me.ID) shpooks.Add(s);
formatter.Serialize(ms, shpooks);
break;
}
socket.Send(ms.GetBuffer());
}
static int ReceivePacket()
{
ms.Position = 0;
socket.Receive(ms.GetBuffer());
int code = reader.ReadInt32();
switch (code)
{
case 0:
{
Console.WriteLine("Catch");
Console.WriteLine(ms.ToString());
bool IsConected = reader.ReadBoolean();
if (IsConected)
{
Me.ID = reader.ReadInt32();
return 1;
}
break;
}
case 2:
{
return 1;
break;
}
case 3:
{
Cell[,] cells = (Cell[,])formatter.Deserialize(ms);
for (int i = 0; i < Width; i++)
for (int j = 0; j < Hight; j++)
{
Field[i, j] = new CellButton(new Coordinate(i, j));
Field[i, j].SetCell(cells[i, j]);
}
Ships.Clear();
Ships.AddRange((List<Ship>)formatter.Deserialize(ms));
break;
}
}
return -1;
}
This is the form before calling Draw():
This is how the form looks after calling Draw():
And so, after a request to the server and method Draw():
I spent a lot of time finding solutions, methods like Form.Update() and Form.Refresh() don't help

WPF c# Hangman game : disable wrong letters and show error message and 2 others questions

Ok guys here's my code :
private void btn_Click(object sender, RoutedEventArgs e)
{
MessageBoxResult confirmatBoxResult = System.Windows.MessageBox.Show(
"Êtes-vous sûr ?", "Confirmer", System.Windows.MessageBoxButton.YesNo);
if (confirmatBoxResult == MessageBoxResult.Yes)
{
for (char c = 'a'; c <= 'z'; c++)
{
char ch = c;
Button btn = new Button();
btn.Content = c;
btn.Width = 60;
btn.Height = 60;
btn.FontSize = 36;
panel_lettre.Children.Add(btn);
lookupLetters[ch] = new List<Label>();
btn.Click += new RoutedEventHandler(btnLetter_Click);
void btnLetter_Click(object sender2, RoutedEventArgs e2)
{
if (lookupLetters.TryGetValue(ch, out List<Label> textList))
{
foreach (var el in textList)
{
el.Content = ch;
btn.IsEnabled = false;
}
}
else
{
foreach (var el in textList)
{
el.Content = ch;
btn.IsEnabled = false;
// not correct
}
}
}
}
foreach (char ch in txtMot.Text)
{
Label Lbl = new Label();
Lbl.Content = ch;
Lbl.Content = "_";
Lbl.FontSize = 36;
Lbl.Width = 30;
lookupLetters[ch].Add(Lbl);
panel_label.Children.Add(Lbl);
}
btnMotProposé.IsEnabled = false;
}
}
With the dictionnary :
public Dictionary<char, List<Label>> lookupLetters = new Dictionary<char, List<Label>>();
I managed to show the 26 letters of the alphabet.
They all are button, and show dynamically in a label on click through : btnClick.
Yet again, an event coming from btnLetter_Click is launched once you click on each button.
Here comes the Dictionnary : it override the content of the label, (_), to replace it with the letter of the word being guessed.
So basically,
If the word is test :
It shows : _ _ _ _
Once I click on the correct alphabet letters that are buttons, it shows the word's letters step by step, until all the letters are fully shown.
Here's my questions :
How can I make it that if I click on any letter that don't match in my word, here test, it makes the letter disabled, (btn.IsEnabled = false;), then cast a MessageBox.Show("Wrong letter !); ?
If the word is found, it cast a : MessageBox.Show("Well done, you've found the word !)
And let's say after 4 attempts, if the user keep casting mistakes, it shows the word being guess?
Here's my crude version of what your looking for:
public partial class MainWindow : Window
{
private int MaxAttempts = 4;
public MainWindow()
{
InitializeComponent();
}
private void btnMotPropose_Click(object sender, RoutedEventArgs e)
{
MessageBoxResult confirmatBoxResult = System.Windows.MessageBox.Show(
"Êtes-vous sûr ?", "Confirmer", System.Windows.MessageBoxButton.YesNo);
var lookupLetters = new Dictionary<char, List<Label>>();
if (confirmatBoxResult == MessageBoxResult.Yes)
{
int attemptCounter = 0;
for (char c = 'a'; c <= 'z'; c++)
{
char ch = c;
Button btn = new Button();
btn.Content = c;
btn.Width = 60;
btn.Height = 60;
btn.FontSize = 36;
panel_lettre.Children.Add(btn);
lookupLetters[ch] = new List<Label>();
btn.Click += new RoutedEventHandler(btnLetter_Click);
void btnLetter_Click(object sender2, RoutedEventArgs e2)
{
if (lookupLetters.TryGetValue(ch, out List<Label> textList))
{
attemptCounter++;
foreach (var el in textList)
{
el.Content = ch;
btn.IsEnabled = false;
}
if (!textList.Any())
{
btn.IsEnabled = false;
MessageBox.Show("Wrong letter!");
}
if (attemptCounter == MaxAttempts)
{
MessageBox.Show("Max attempts reached!");
ShowAnswer(lookupLetters);
}
if (AreAllLettersUncovered())
{
MessageBox.Show("Well done, you've found the word !!");
}
}
}
}
foreach (char ch in txtMot.Text)
{
Label Lbl = new Label();
Lbl.Content = "_";
Lbl.FontSize = 36;
Lbl.Width = 30;
lookupLetters[ch].Add(Lbl);
panel_label.Children.Add(Lbl);
}
btnMotPropose.IsEnabled = false;
}
}
private bool AreAllLettersUncovered()
{
return panel_label.Children.Cast<Label>().All(p => (string)p.Content != "_");
}
private void ShowAnswer(Dictionary<char, List<Label>> lookupLetters)
{
var lettersWithLabels = lookupLetters.Where(p => p.Value.Any());
foreach (var letterWithLabel in lettersWithLabels)
{
foreach (var label in letterWithLabel.Value)
{
label.Content = letterWithLabel.Key.ToString();
}
}
}
}
As side comments - I'd decouple the dynamic on click event handler into a separate method - it would make the code more readable. The main onClick method is quite long and not easily readable. Your naming convention differs from variable too variable (mixed sometimes with underscore, english/non-english). It's easier to read code when the naming convention is unchanging.

Extender controls may not be registered after PreRender. Controls added dynamically

I am adding controls to a form dynamically, then reading back the responses. To do this, I have to recreate the form on postback before trying to get at the responses.
At present, only fields that require a date have an AjaxControlToolkit MaskedEditExtender:
case "DAT":
TextBox tb = new TextBox();
tb.ID = "tbDat" + intQuestionCount.ToString();
tb.CssClass = "PositionCol3 SVSTextBox1";
tb.Width = 250;
// check for date range restricdtions and display in tooltip
strTooltip = "";
if (question.DateMaxDaysInPast != 0)
{
DateTime dtPastDate = DateTime.Now.AddDays(-Convert.ToInt32(question.DateMaxDaysInPast));
strTooltip = "Date must be after " + dtPastDate.ToShortDateString();
}
if (question.DateMaxDaysInFuture != 0)
{
DateTime dtFutureDate = DateTime.Now.AddDays(Convert.ToInt32(question.DateMaxDaysInFuture));
if (strTooltip == "")
{
strTooltip = "Date must be before " + dtFutureDate.ToShortDateString();
}
else
{
strTooltip += " and before " + dtFutureDate.ToShortDateString();
}
}
tb.ToolTip = strTooltip; ;
// if this is a completed form look for saved response
if (intCompletedSurveyAnswerId != 0)
{
tb.Text = strAnswerText;
}
questionsPanel.Controls.Add(tb);
// add to list of controls
m_orderOfControls[intNumOfControls] = "TB";
intNumOfControls += 1;
// add to saved textboxes
m_dynamicTextBoxes[intTextBoxCount] = tb;
intTextBoxCount += 1;
// try add masked edit extender
AjaxControlToolkit.MaskedEditExtender maskedEdit = new AjaxControlToolkit.MaskedEditExtender();
maskedEdit.ID = "mk_" + tb.ID;
maskedEdit.TargetControlID = tb.ID;
maskedEdit.Mask = "99/99/9999";
maskedEdit.MaskType = AjaxControlToolkit.MaskedEditType.Date;
//maskedEdit.InputDirection = AjaxControlToolkit.MaskedEditInputDirection.RightToLeft;
questionsPanel.Controls.Add(maskedEdit);
// add to list of controls
m_orderOfControls[intNumOfControls] = "MK";
intNumOfControls += 1;
// add to saved textboxes
m_dynamicMasks [intMaskCount] = maskedEdit;
intMaskCount += 1;
break;
m_orderOfControls, intNumOfControls, m_dynamicMasks, intMaskCount are all save as session vaiables, so that the form can be recreated on postback:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
retrieveDynamicControlsFromSession();
recreateForm();
}
and:
protected void recreateForm()
{
//
// Form needs to be recreated after postback exactly as want sent out
//
try
{
int intNumOfLabels = 0;
int intNumOfTextBoxes = 0;
int intNumDdls = 0;
int intNumCbls = 0;
int intNumRbls = 0;
int intNumCbs = 0;
int intNumLitControls = 0;
int intNumMaskedEditExtenders = 0;
questionsPanel.Controls.Clear();
foreach (string controlType in m_orderOfControls)
{
if (controlType != null)
{
LiteralControl htmlControl = new LiteralControl();
switch (controlType)
{
case "MK":
AjaxControlToolkit.MaskedEditExtender maskedEdit = new AjaxControlToolkit.MaskedEditExtender();
maskedEdit = m_dynamicMasks[intNumMaskedEditExtenders];
intNumMaskedEditExtenders += 1;
questionsPanel.Controls.Add(maskedEdit);
break;
case "LB":
Label lbl = new Label();
lbl = m_dynamicLabels[intNumOfLabels];
intNumOfLabels += 1;
questionsPanel.Controls.Add(lbl);
break;
case "TB":
TextBox textBox = new TextBox();
textBox = m_dynamicTextBoxes[intNumOfTextBoxes];
intNumOfTextBoxes += 1;
questionsPanel.Controls.Add(textBox);
break;
case "CB":
CheckBox checkBox = new CheckBox();
checkBox = m_dynamicCheckBoxes[intNumCbs];
intNumCbs += 1;
questionsPanel.Controls.Add(checkBox);
break;
case "CBL":
CheckBoxList checkBoxList = new CheckBoxList();
checkBoxList = m_dynamicCheckBoxLists[intNumCbls];
intNumCbls += 1;
questionsPanel.Controls.Add(checkBoxList);
break;
case "RBL":
RadioButtonList radioButtonList = new RadioButtonList();
radioButtonList = m_dynamicRadioButtonLists[intNumRbls];
intNumRbls += 1;
questionsPanel.Controls.Add(radioButtonList);
break;
case "HTML":
LiteralControl hmtlControl = new LiteralControl();
htmlControl = m_literalControls[intNumLitControls];
intNumLitControls += 1;
questionsPanel.Controls.Add(htmlControl);
break;
case "DDL":
DropDownList dropDownList = new DropDownList();
dropDownList = m_dynamicDropDownLists[intNumDdls];
intNumDdls += 1;
questionsPanel.Controls.Add(dropDownList);
break;
default:
break;
}
// end paragraph
}
}
}
catch (Exception ex)
{
throw ex;
}
}
On testing this, after form Save button has been used once or twice, I get this error: Extender controls may not be registered after PreRender.
Any ideas?

How to find label controls in an asp.net page

I have some label controls in a panel with id ResultsPanel. To find the label controls on the page, I did the following:
for (int ctr = 0; ctr < lblString.Length - 1; ctr++)
{
//string labelID = string.Format("lblResult{0}", ctr);
int mylbl = ctr + 1;
string lblResult = ((Label)ResultsPanel.FindControl("lblResult" + mylbl.ToString())).Text;
lblResult = lblString[mylbl].ToString();
}
lblResult1.Text = lblString.ToString();
lblString is a stringBuilder Object with 24 numbers. The Idea is to map each of the numbers in the stringbuilder object to labels in this manner:
lblResult1.Text = lblString[mylbl].ToString(); to the 24th label. But I can't seem to generate the labels and map the values to the label control.
Change the line to
Label lblResult = ((Label)ResultsPanel.FindControl("lblResult" + mylbl.ToString()));
lblResult.Text = lblString[mylbl].ToString();
Your question and code are a bit misleading, but I will try my best anyway.
Your code:
for (int ctr = 0; ctr < lblString.Length - 1; ctr++)
{
//string labelID = string.Format("lblResult{0}", ctr);
int mylbl = ctr + 1;
string lblResult = ((Label)ResultsPanel.FindControl("lblResult" + mylbl.ToString())).Text;
lblResult = lblString[mylbl].ToString();
}
lblResult1.Text = lblString.ToString();
If you have labels in the order of label1, label2, label3 ... then I would write something like this:
private void MapLabels()
{
var labelsResult = string.Empty;
var labelString = "123456789";
for (int i = 0; i < labelString.Length; i++)
{
var control = this.FindControl("label" + labelString[i]);
if(control != null)
{
labelsResult += ((Label)control).Text;
}
}
labelResult1.Text = labelsResult;
}
Let me know if you get stuck.
Hope this will help you. Like this you can get the value of label too.
public void GetControlsValuePopulated(Control control, Type controlType, Dictionary<string, string> dictControlPageValParam)
{
try
{
if (control.HasControls())
{
GetControlsValuePopulated(control, controlType, dictControlPageValParam);
}
else
{
if (controlType == null || controlType.IsAssignableFrom(control.GetType()))
{
if (control.ID != null)
{
bool FoundControl = dictControlPageValParam.ContainsKey(control.ID.Substring(3));
if (FoundControl)
{
switch (control.GetType().ToString())
{
case "System.Web.UI.WebControls.TextBox":
TextBox txt = (TextBox)control;
txt.Text = dictControlPageValParam[txt.ID.Substring(3)];
break;
case "System.Web.UI.WebControls.CheckBox":
CheckBox chk = (CheckBox)control;
if (dictControlPageValParam[chk.ID.Substring(3)].ToUpper() == "TRUE" || dictControlPageValParam[chk.ID.Substring(3)].ToUpper() == "T")
{
chk.Checked = true;
}
else
{
chk.Checked = false;
}
break;
case "System.Web.UI.WebControls.DropDownList":
DropDownList ddl = (DropDownList)control;
//ddl.SelectedValue = dictControlPageValParam[ddl.ID.Substring(3)];
break;
case "System.Web.UI.WebControls.RadioButtonList":
RadioButtonList rbl = (RadioButtonList)control;
rbl.SelectedValue = dictControlPageValParam[rbl.ID.Substring(3)];
break;
case "System.Web.UI.WebControls.HiddenField":
HiddenField hdn = (HiddenField)control;
hdn.Value = dictControlPageValParam[hdn.ID.Substring(3)];
break;
}
}
}
}
}
}
catch (Exception)
{
throw;
}
}
public void GetChildControlsId(Control control, Type controlType)
{
try
{
if (control.HasControls())
{
GetChildControlsId(control, controlType);
}
else
{
if (controlType == null || controlType.IsAssignableFrom(control.GetType()))
{
///checking if control already existing in the collection
if (control.ID != null)
{
bool FoundControl = controlHt.ContainsKey(control.ID);
if (!FoundControl)
{
switch (control.GetType().ToString())
{
case "System.Web.UI.WebControls.TextBox":
TextBox txt = (TextBox)control;
controlTypeName = txt.ID;
controlTypeName = controlTypeName.Substring(3);
controlTypeValue = txt.Text;
if (dictControlValParam.ContainsKey(controlTypeName) == false)
{
dictControlValParam.Add(controlTypeName, controlTypeValue);
}
else
{
dictControlValParam.Remove(controlTypeName);
dictControlValParam.Add(controlTypeName, controlTypeValue);
}
break;
case "System.Web.UI.WebControls.CheckBox":
CheckBox chk = (CheckBox)control;
controlTypeName = chk.ID;
controlTypeName = controlTypeName.Substring(3);
controlTypeValue = chk.Checked.ToString();
if (dictControlValParam.ContainsKey(controlTypeName) == false)
{
dictControlValParam.Add(controlTypeName, controlTypeValue);
}
else
{
dictControlValParam.Remove(controlTypeName);
dictControlValParam.Add(controlTypeName, controlTypeValue);
}
break;
case "System.Web.UI.WebControls.DropDownList":
DropDownList ddl = (DropDownList)control;
controlTypeName = ddl.ID;
controlTypeName = controlTypeName.Substring(3);
controlTypeValue = ddl.SelectedValue.ToString();
if (dictControlValParam.ContainsKey(controlTypeName) == false)
{
dictControlValParam.Add(controlTypeName, controlTypeValue);
}
else
{
dictControlValParam.Remove(controlTypeName);
dictControlValParam.Add(controlTypeName, controlTypeValue);
}
break;
case "System.Web.UI.WebControls.RadioButtonList":
RadioButtonList rbl = (RadioButtonList)control;
controlTypeName = rbl.ID;
controlTypeName = controlTypeName.Substring(3);
controlTypeValue = rbl.SelectedValue.ToString();
if (dictControlValParam.ContainsKey(controlTypeName) == false)
{
dictControlValParam.Add(controlTypeName, controlTypeValue);
}
else
{
dictControlValParam.Remove(controlTypeName);
dictControlValParam.Add(controlTypeName, controlTypeValue);
}
break;
case "System.Web.UI.WebControls.HiddenField":
HiddenField hdn = (HiddenField)control;
controlTypeName = hdn.ID;
controlTypeName = controlTypeName.Substring(3);
controlTypeValue = hdn.Value;
if (dictControlValParam.ContainsKey(controlTypeName) == false)
{
dictControlValParam.Add(controlTypeName, controlTypeValue);
}
else
{
dictControlValParam.Remove(controlTypeName);
dictControlValParam.Add(controlTypeName, controlTypeValue);
}
break;
}
}
}
}
}
}
catch (Exception)
{
throw;
}
}

Stackoverflow exception from updating combobox in winforms/C#

I'm geting a StackOverflowException. Somehow, posting here seemed appropriate.
I'm using Windows Forms in a C# application. This application is intended to run on Linux, FreeBSD and Mac-OS, so I can't use WPF, so please don't suggest it.
My guess is that I'm missing a nuance of WinForms, but I cant seem to figure out what.
The ComboBox is generated by the GUI form builder in VS 2010.
The specific lines of code that are throwing the error are here:
if(cur_num_is_valid)
{
cbx_material_num.Text = num;
}
else
{
num = "0";
//I only have one of the following two at a time. Both overflow
cbx_material_num.SelectedIndex = 0;
cbx_material_num.Text = "0";
}
Since the code is somewhat complex, here's the whole function code. 'cbx_' indicates a combo box. 'txtb_' is a text box.
private void cbx_material_numobj_SelectedIndexChanged(object sender, EventArgs e)
{
string obj = cbx_material_obj.Text;
string num = cbx_material_num.Text;
int selnum = 0;
int n = 0;
//do we need to recreate the numbers array?
bool cur_num_is_valid = false;
cbx_material_num.Items.Clear();
if(obj != lastobj)
{
n = m_demo.get_object_modifiers(obj);
for(int i = 0; i <= n; i++)
{
string s = i.ToString();
if(s == num && i < n) cur_num_is_valid = true;
cbx_material_num.Items.Add(s);
}
}
if(cur_num_is_valid)
{
cbx_material_num.Text = num;
}
else
{
num = "0";
//Overflow here:
cbx_material_num.SelectedIndex = 0;
}
try
{
selnum = int.Parse(num);
}
catch(Exception)
{
MessageBox.Show("Error, second select menu after 'object modifiers' must be a number, not '"+num+"'.");
cbx_material_num.Text="0";
return;
}
if(selnum >= n)
{
txtb_material_param1.Text = "0";
txtb_material_param2.Text = "0";
txtb_material_param3.Text = "0";
txtb_material_param4.Text = "0";
}
else
{
MaterialFace face;
MaterialParameter parameter;
int typeid;
object paramdata;
m_demo.get_object_modifiers_material(obj, selnum, out face, out parameter, out typeid, out paramdata);
cbx_material_face.Text = face.ToString();
cbx_material_paramtype.Text = parameter.ToString();
switch(typeid)
{
case 0:
txtb_material_param1.Text = ((float)paramdata).ToString();
cbx_material_datatype.Text = "float";
goto case -1;
case 1:
float[] parsf = ((float[])paramdata);
txtb_material_param1.Text = parsf[0].ToString();
txtb_material_param2.Text = parsf[1].ToString();
txtb_material_param3.Text = parsf[2].ToString();
txtb_material_param4.Text = parsf[3].ToString();
cbx_material_datatype.Text = "float[]";
break;
case 2:
txtb_material_param1.Text = ((int)paramdata).ToString();
cbx_material_datatype.Text = "int";
goto case -1;
case 3:
int[] parsi = ((int[])paramdata);
txtb_material_param1.Text = parsi[0].ToString();
txtb_material_param2.Text = parsi[1].ToString();
txtb_material_param3.Text = parsi[2].ToString();
txtb_material_param4.Text = parsi[3].ToString();
cbx_material_datatype.Text = "int[]";
break;
case -1: //can't actuall be returned, used to 'blank' the last three as '0'
txtb_material_param2.Text = "0";
txtb_material_param2.Text = "0";
txtb_material_param3.Text = "0";
break;
case 4:
OpenTK.Graphics.Color4 paramc = ((OpenTK.Graphics.Color4)paramdata);
txtb_material_param1.Text = paramc.R.ToString();
txtb_material_param2.Text = paramc.G.ToString();
txtb_material_param3.Text = paramc.B.ToString();
txtb_material_param4.Text = paramc.A.ToString();
cbx_material_datatype.Text = "Color4";
break;
default: //5
Vector4 paramv = ((Vector4)paramdata);
txtb_material_param1.Text = paramv.X.ToString();
txtb_material_param2.Text = paramv.Y.ToString();
txtb_material_param3.Text = paramv.Z.ToString();
txtb_material_param4.Text = paramv.W.ToString();
cbx_material_datatype.Text = "Vector4";
break;
}
}
}
You need to check that the SelectedIndex isn't already 0 before you try to set it:
if (cbx_material_num.SelectedIndex != 0){
cbx_material_num.SelectedIndex = 0;
}
Otherwise you're re-firing the event every time through.
I think that whenever you set this cbx_material_num.SelectedIndex = 0; within the EventHandler you invoke your
cbx_material_numobj_SelectedIndexChanged(object sender, EventArgs e)
Each call invokes another eventHandler so the stack fills up after some time.
Basically, the fact that it is called SelectedIndexChanged doesn't mean that the value has to be different from the previous one but that the value is set through its setter.

Categories

Resources