I am making an online form. I initialise 4 variables in my code at the beginning. When I select a dropdown, an event (DropDownList4_SelectedIndexChanged ) gets fired which in turn call Availability(). Here my boolean variable avail_bus is assigned a value. However, when i click on submit button ( Button1_Click1), the variable avail_bus is reinitialised to false. I debugged this and found out that upon clicking on Submit(Button1_Click1) the control first goes to the top of the code in the page which is
public partial class Appform : System.Web.UI.Page
{
private bool isNotDup = true;
private bool avail_bus ;
private int max_capacity_bus;
private int realAvailability;
}
and then goes to Button1_click1 .
How can I prevent this from happening ? If the state of avail_bus is changed to true while calling availability, it should not get reinitialized to true when i click on submit.
Below is my code :
namespace eTransport
{
public partial class Appform : System.Web.UI.Page
{
private bool isNotDup = true;
private bool avail_bus ;
private int max_capacity_bus;
private int realAvailability;
protected void Page_Load (object sender, EventArgs e)
{
if (!this.IsPostBack)
{
BindDropDown();
}
}
//Method called when dropdown is selected in Bus Stop. It helps to populate Bus Number
protected void DropDownList4_SelectedIndexChanged (object sender, EventArgs e)
{
AutoPopulateBusStop();
Availability();
}
//Method to load drop down values in Bus Stop. These are populated from database
protected void BindDropDown ()
{
//some code here
}
//Method to autopopulate Bus Number based on selection of Bus Stop. The mapping is in the database in the table named -> dropdownlist
protected void AutoPopulateBusStop ()
{
//some code here
}
protected void Availability ()
{
string constr5 = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
using (SqlConnection con5 = new SqlConnection(constr5))
{
try
{
using (SqlCommand cmd5 = new SqlCommand("select count(*) from etms where BusNo='" + TextBox6.Text.ToString() + "'"))
{
cmd5.CommandType = CommandType.Text;
cmd5.Connection = con5;
con5.Open();
int capacity_from_db = Convert.ToInt16(cmd5.ExecuteScalar());
realAvailability = max_capacity_bus - capacity_from_db;
if (realAvailability > 0)
{
avail_bus = true;
TextBox2.Text = realAvailability.ToString() + " seats available ";
TextBox2.ForeColor = System.Drawing.ColorTranslator.FromHtml("#008000");
}
else
{
TextBox2.Text = "Seats Not available. Please choose another Stop";
TextBox2.ForeColor = System.Drawing.ColorTranslator.FromHtml("#ff1919");
}
}
}
catch (Exception ex)
{
Response.Write(ex);
}
}
}
protected void Button1_Click1 (object sender, EventArgs e)
{
if (isNotDup)
{
if (avail_bus)
{
// Submit the Form
}
else
{
Label14.Text = "Bus Seats not available!";
Label15.Text = null;
}
}
}
protected void PhoneNumberValidatation (object source, ServerValidateEventArgs args)
{
//some code here
}
}
}
There are three possible solution for this question.
Static - This will create one instance that accessible to all pages (Global).
private static avail_bus = true;
Session State - This enables you to store and retrieve values for a user as the user navigates.
// Get...
private bool avail_bus = (bool)Session["avail_bus"];
// Set
Session["avail_bus"] = true;
Control.ViewState - Gets a dictionary of state information that allows you to save and restore the view state of a server control across multiple requests for the same page.
public bool avail_bus
{
get { return ViewState["avail_bus"] == null ? false : (bool)ViewState["avail_bus"]; }
set { ViewState["avail_bus"] = value; }
}
Every time there is a request for your page, a new instance of that page-class is created to handle that request. So any fields are re-initialized.
You can store a value in ViewState to remember a value over various requests:
namespace eTransport
{
public partial class Appform : System.Web.UI.Page
{
private bool isNotDup
{
set { ViewState["isNotDup "] = value; }
get
{
if (ViewState["isNotDup "] == null)
return true;
return (bool )ViewState["isNotDup "];
}
}
private bool avail_bus
{
set { ViewState["avail_bus"] = value; }
get
{
if (ViewState["avail_bus"] == null)
return true;
return (bool )ViewState["avail_bus"];
}
}
private int max_capacity_bus
{
set { ViewState["max_capacity_bus "] = value; }
get
{
if (ViewState["max_capacity_bus "] == null)
return 0;
return (int)ViewState["max_capacity_bus "];
}
}
private int realAvailability
{
set { ViewState["realAvailability"] = value; }
get
{
if (ViewState["realAvailability"] == null)
return 0;
return (int)ViewState["realAvailability"];
}
}
protected void Page_Load (object sender, EventArgs e)
{
if (!this.IsPostBack)
{
BindDropDown();
}
}
//Method called when dropdown is selected in Bus Stop. It helps to populate Bus Number
protected void DropDownList4_SelectedIndexChanged (object sender, EventArgs e)
{
AutoPopulateBusStop();
Availability();
}
//Method to load drop down values in Bus Stop. These are populated from database
protected void BindDropDown ()
{
//some code here
}
//Method to autopopulate Bus Number based on selection of Bus Stop. The mapping is in the database in the table named -> dropdownlist
protected void AutoPopulateBusStop ()
{
//some code here
}
protected void Availability ()
{
string constr5 = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
using (SqlConnection con5 = new SqlConnection(constr5))
{
try
{
using (SqlCommand cmd5 = new SqlCommand("select count(*) from etms where BusNo='" + TextBox6.Text.ToString() + "'"))
{
cmd5.CommandType = CommandType.Text;
cmd5.Connection = con5;
con5.Open();
int capacity_from_db = Convert.ToInt16(cmd5.ExecuteScalar());
realAvailability = max_capacity_bus - capacity_from_db;
if (realAvailability > 0)
{
avail_bus = true;
TextBox2.Text = realAvailability.ToString() + " seats available ";
TextBox2.ForeColor = System.Drawing.ColorTranslator.FromHtml("#008000");
}
else
{
TextBox2.Text = "Seats Not available. Please choose another Stop";
TextBox2.ForeColor = System.Drawing.ColorTranslator.FromHtml("#ff1919");
}
}
}
catch (Exception ex)
{
Response.Write(ex);
}
}
}
protected void Button1_Click1 (object sender, EventArgs e)
{
if (isNotDup)
{
if (avail_bus)
{
// Submit the Form
}
else
{
Label14.Text = "Bus Seats not available!";
Label15.Text = null;
}
}
}
protected void PhoneNumberValidatation (object source, ServerValidateEventArgs args)
{
//some code here
}
}
}
You can store the availability status in a hidden input field which later gets posted on Button1 click event.
And in button1 click event instead of accessing the avail value from variable access it from hiddenField's value
Another option would be calling Availability() again in click event of button1 as a first line so that it sets proper value in the avail_bus variable
Related
DataGridView Image Column is getting null when change the visibility of User Control that includes the dataGridView. Codes are below;
public partial class ReadingOrderListControl : UserControl
{
private Image Pending { get { return Image.FromFile(#"..\..\Resources\pending.png"); } }
private Image Completed { get { return Image.FromFile(#"..\..\Resources\completed.png"); } }
private void ReadingOrderListControl_Load(object sender, EventArgs e)
{
GetOrderList();
}
private void GetOrderList()
{
dgv_ReadingOrders.DataSource = DbManager.GetReadingOrders();
if (dgv_ReadingOrders.Rows[0].Cells["tamamlanma"].Value.ToString() == "1")
dgv_ReadingOrders.Rows[0].Cells["tamamlanma_image"].Value = Completed;
else
dgv_ReadingOrders.Rows[0].Cells["tamamlanma_image"].Value = Pending;
}
}
Try this:
if (dgv_ReadingOrders.Rows[0].Cells["tamamlanma"].Value.ToString() == "1")
dgv_ReadingOrders.Rows.Add(ID,...... , Bitmap.FromFile(Completed));
else
dgv_ReadingOrders.Rows.Add(ID,...... , Bitmap.FromFile(Pending));
I have a UserControl and a class for updating/storing results in a database. I need to automatically refresh the UserControlResultDislpay upon storing data. I have created and event to trigger a refresh when an Update occurs. I have the following code:
Class InstrumentTest:
public delegate void UpdateResultDisplay(object sender, EventArgs e);
public event UpdateResultDisplay RefreshDisplay;
protected virtual void OnNewResult(EventArgs e)
{
if (RefreshDisplay != null)
RefreshDisplay(this, e);
}
public void UpdateResultDB(ResultDataJFTOT resultData)
{
AnalysisListCommon myresult = PContext.GetInstance().DbHandlerLocal.StoredResult(
resultData.SampleId,
resultData.TestDate.ToString("yyyy-MM-ddTHH:mm", CultureInfo.InvariantCulture),
resultData.InstrumentSn,
StringRepository.constStringSampleName);
if (myresult != null)
{
Result r = new Result(new Guid(myresult.ResultId));
ResultData rd = r.GetResultData("Rating", FindResultDataMode.byVariableIdentifier);
string xmlTubeRating = resultData.tRating.ToString().Replace("#LT#", "<");
rd.Text = xmlRating;
rd.Store();
rd = r.GetResultData("TestDate", FindResultDataMode.byVariableIdentifier);
rd.Text = resultData.Date.ToString();
rd.Store();
OnNewResult(EventArgs.Empty);
}
else
{
AddTestToQueue(resultData);
}
}
public static InstrumentTest Instance()
{
//If instance is null create a new instance of the InstrumentTest
if (instrumentTestInstance == null)
{
instrumentTestInstance = new InstrumentTest();
}
return instrumentTestInstance;
}
Code from UserControl:
public UserControlResultDisplay()
{
this.InitializeComponent();
this.InitializeUIStrings();
this.InitializePlot();
EventListener(resultChanged);
}
private InstrumentTest resultChanged = InstrumentTest.Instance();
public void EventListener(InstrumentTest resultChanged)
{
//resultChanged = (InstrumentTest)obj;
resultChanged.RefreshDisplay += DisplayNewResultData;
}
private void DisplayNewResultData(object sender, EventArgs e)
{
RefreshCurrentResult();
}
Ok guy,
i have made a simple program that has a web form where you fill in details fruit name, kg and cal count. i have then used session variables to get the fruit name from the form on default page and display them on about page in a drop down menu. that's all working fine, what i cant seem to work out is on the about page how to get it so the user selects a item from the drop down (created from form on default page) then enter a int how many they want (in text box) and have there selection and amount output on a list box on about page. il post the code i have so far any help would be much appreciated.
default page
public class Fruit
{
private string fName;
private int grams, calsPerGram;
private bool edible;
public Fruit(string n, int g, int c, bool e)
{
grams = g;
calsPerGram = c;
edible = e;
fName = n;
}
public int totalCalories()
{
return grams * calsPerGram;
}
public string getFruitInfo()
{
string s;
if (edible == true)
{
s = fName + " is yummy and it has " + totalCalories() +
"calories";
}
else
{
s = "Hands off! Not edible";
}
return s;
}
}
public partial class _Default : System.Web.UI.Page
{
List<Fruit> myBasket;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
myBasket = new List<Fruit>();
Session["listSession"] = myBasket;// seassion start
}
}
protected void Button1_Click1(object sender, EventArgs e)
{
// Session["Fruitname"] = TbxName.Text; // my session i have made
MyFruit = Session["Fruitname"] as List<string>;
//Create new, if null
if (MyFruit == null)
MyFruit = new List<string>();
MyFruit.Add(TbxName.Text);
Session["Fruitname"] = MyFruit;
abc.Items.Clear();
Fruit f = new Fruit(TbxName.Text, int.Parse(TbxWeight.Text),
int.Parse(TbxCal.Text), CheckBox1.Checked);
myBasket = (List<Fruit>)Session["listSession"]; // session used
myBasket.Add(f);
foreach (var item in myBasket)
{
abc.Items.Add(item.getFruitInfo()); // List box used
}
}
public List<string> MyFruit { get; set; }
}
About page
public partial class About : Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyFruit = Session["Fruitname"] as List<string>;
//Create new, if null
if (MyFruit == null)
MyFruit = new List<string>();
DropDownList1.DataSource = MyFruit;
DropDownList1.DataBind();
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
Drinklabel.Text = "Your Chosen Beverage is A " + DropDownList1.SelectedValue.ToString() + " Drink.";
}
public List<string> MyFruit { get; set; }
}
You do not necessarily need a separate class for calculating cost, but I recommend that you use a Label to display the selected fruit, amount desired and total price, like this in your About page:
Create a Button with Calculate text that has a click event handler, a calculatePrice method, a TextBox for quantity and a Label for display, like this:
protected void ButtonCalculate_Click(sender object, EventArgs e)
{
decimal total = calculatePrice(DropDownList1.SelectedItem.Text,
TextBoxQuantity.Text.Trim());
LabelResult.Text = "You would like " + TextBoxQuantity.Text.Trim() +
DropDownList1.SelectedItem.Text + "(s) for a total of $" +
total.ToString();
}
private decimal calculatePrice(string fruitName, int quantity)
{
// Ask the database for the price of this particular piece of fruit by name
decimal costEach = GoToDatabaseAndGetPriceOfFruitByName(fruitName);
return costEach * quantity;
}
I'm studying design patterns right now, I'm fairly new to this model-view-presenter, although I have already experience in asp.net mvc I'm trying to do an implementation of mvp in winforms.
The string in the textbox will be sorted with an algorithm based on the combobox. Right now when I click the button it throws a null reference exception
Here is the UI:
Here are my classes and codes:
class FormPresenter
{
private ISortingView _view;
private string _algorithm;
private StringToSortModel sortMe = new StringToSortModel();
public FormPresenter(ISortingView view)
{
_view = view;
_view.sortTheString += view_sortString;
sortMe.sortThis = view.stringToSort;
_algorithm = _view.algorithm;
//Algorithm = view.stringToSort;
//sortingform.sortTheString += (obj
}
private void view_sortString(object sender, EventArgs e)
{
SortContext context = new SortContext();
_view.sortedText = context.Sort(sortMe.sortThis.ToCharArray());
}
}
interface ISortingView
{
event EventHandler sortTheString;
string stringToSort { get; }
string algorithm { get; }
string sortedText { get; set; }
}
public partial class SortingForm : Form, ISortingView
{
public SortingForm()
{
InitializeComponent();
comboBox1.Items.Add("Bubble Sort");
comboBox1.Items.Add("Insertion Sort");
comboBox1.SelectedItem = "Bubble Sort";
textBox1.Text = "Emiri";
}
public event EventHandler sortTheString;
public string algorithm { get { return comboBox1.SelectedItem.ToString(); } }
public string stringToSort { get { return textBox1.Text; } }
public string sortedText { get { return label2.Text; } set { label2.Text = value; } }
private void Form1_Load(object sender, EventArgs e)
{
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
//char[] x = textBox1.Text.ToCharArray();
//SortContext con = new SortContext();
//con.SetSortStrategy(new InsertionSort());
//label2.Text = con.Sort(x);
//if(sortString != null)
//{
//this prodcues a null exception error
sortTheString(sender, e);
//}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var mainForm = new SortingForm();
var presenter = new FormPresenter(mainForm);
Application.Run(new SortingForm());
}
}
I have not included the codes for the model and the classes the contains the sorting functions to keep this post short. The problem I have is that when button is clicked it throws a null reference exception error, something that I have been stuck on for hours already.
Sir/Ma'am your answers would be of great help. Thank you++
Your null is coming from this line
sortTheString(sender, e);
because you are not using the same form instance in your Presenter. Change to this in your main...
Application.Run(mainForm);
The event handler does not have any subscribers (because of the Application.Run(new SortingForm()); C# will treat that as null rather than an empty subscriber list.
ISortingView mainForm = new SortingForm();
var presenter = new FormPresenter(mainForm);
Application.Run(mainForm as Form);
I've been puzzling over this one for a few days now and it's got me pretty beaten, but to be honest I'm not all that experienced yet and I'm having trouble with DataGridView - which seems a common topic.
public partial class frmMain : Form
{
ServerConnection sabCom;
private BindingSource jobSource = new BindingSource();
private void timer1_Tick(object sender, EventArgs e)
{
if (bgUpdateThread.IsBusy == false)
{
bgUpdateThread.RunWorkerAsync(sabCom);
}
}
}
private void frmMain_Load(object sender, EventArgs e)
{
timer1.Interval = 3000;
timer1.Start();
}
private void bgUpdateThread_DoWork(object sender, DoWorkEventArgs e)
{
ServerConnection s = e.Argument as ServerConnection;
s.update();
e.Result = s;
}
private void bgUpdateThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.sabCom = e.Result as ServerConnection;
if (dgvQueueFormatted == false)
{
dgvQueue_Init(); //Applies formatting and loads column width. Inits data sources.
}
else
{
dgvQueue_Update();
}
}
private void dgvQueue_Update()
{
dgvQueue.Refresh();
}
private void dgvQueue_Init()
{
try
{
jobSource.DataSource = sabCom.queue.jobs;
dgvQueue.DataSource = jobSource;
try
{
//Apply saved column spacing to the dgvQueue
//Uses reflection to set dgvQueue to DoubleBuffer
}
catch
{ }
}
catch
{ }
}
private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
//Saves information about the dgvQueue on shutdown.
}
Queue Class:
public class Queue
{
private string _status;
public string status { get { return _status; } set { _status = value; } }
private string _eta;
public string eta { get { return _eta; } set { _eta = value; } }
private List<Job> _jobs;
public List<Job> jobs
{
get
{
return _jobs;
}
set
{
_jobs = value;
}
}
private List<string> _categories;
public List<string> categories { get { return _categories; } set { _categories = value; } }
private XmlDocument xmld;
private ServerConnection m_parent;
private XmlNodeList _xmljobs;
public Queue(ServerConnection srvConn)
{
//fetch the Queue xml
m_parent = srvConn;
xmld = new XmlDocument();
_jobs = new List<Job>();
}
public void update()
{
updateXml();
updateQueue();
updateJobs();
}
private void updateXml()
{
//Loads xml file into xmld
}
private void updateQueue()
{
XmlNodeList elements = xmld.SelectNodes("queue");
foreach (XmlNode element in elements)
{
_status = element.SelectSingleNode("status").InnerText;
_eta = element.SelectSingleNode("eta").InnerText;
}
}
private void updateJobs()
{
_xmljobs = xmld.SelectNodes("queue/job");
jobs.Clear();
foreach (XmlNode xmljob in _xmljobs)
{
Job t_job;
_status = xmljob.SelectSingleNode("status").InnerText;
_eta = xmljob.SelectSingleNode("eta").InnerText;
//Create temp job to match against list.
t_job = new Job(_status, _eta);
jobs.Add(t_job);
}
}
Job class: In reality it holds around 30 values of varying types, but they're all in the same format:
public class Job
{
private int _status;
public int status { get { return _status; } set { _status = value; } }
private string _eta;
public string eta { get { return _eta; } set { _eta = value; } }
public Job(string status, string eta)
{
_status = status;
_eta = eta;
}
}
When interacting with the DataGridView I get the error:
The following exception occured in the DataGridView:
System.IndexOutOfRangeException: Index does not have a value.
at System.Windows.Forms.CurrencyManager.get_Item(Int32 index)
at System.Windows.Forms.DataGridViewDataConnection.GetError(Int32 boundColumnIndex, Int32 columnIndex, Int32 rowIndex)
And when entering the debugger it's triggered on the initial Application.Run(new frmMain(). What on earth am I doing wrong? The program still functions and updates normally but I can't even handle the event to suppress the default error message!
Edit - Answer!
Instead of clearing the list and re-creating it, just updating the values within it works better. For the moment I have this code:
t_job = _jobs.FirstOrDefault(c => c.nzo_id == t_nzo_id);
if (t_job == null) //Job not in list, insert
{
t_job = new Job(t_status, i_index, t_eta, i_timeLeft, t_age, i_mbleft, i_mb, t_filename, i_priority, t_category, i_percentage, t_nzo_id, this);
jobs.Add(t_job);
}
else //update object in current list
{
jobs[t_job.Index].status = t_status;
jobs[t_job.Index].priority = i_priority;
jobs[t_job.Index].category = t_category;
jobs[t_job.Index].percentage = i_percentage;
jobs[t_job.Index].timeleft = i_timeLeft;
jobs[t_job.Index].mbleft = i_mbleft;
}
Which prevents it!
The problem seems to be that with a refresh interval of say 1 second, while the user is scrolling or trying to access the fields of the data the data is constantly being removed and readded.
This causes the binding to to call try call a value that it thinks might still be there, but isn't and that is why you are getting the index out of range exception
The first thing I would suggest doing is in your updateJobs method as well as all the other lists that are refreshed like the queue list, instead of clearing the list everytime is first checking to see if the job from the xml exists in the current job list, if it does then you can change the current values if the value has changed otherwise do nothing.
To check if the job exists it is as easy as:
t_job = _jobs.FirstOrDefault(c => c.Filename == t_filename);
This will return a null if the job does not exist, I would assume filename might not be unique, so might want to change it so that it really is unique i.e.
t_job = _jobs.FirstOrDefault(c => c.Filename == t_filename && c.nzo_id == t_nzo_id);
One thing you will now have to cater for is that old jobs won't be automatically removed, so whenever a new history job is added, first check to see if it exists in the queue and then remove it there before adding it to the history list.
so change your properties to be:
public int Index
{
get { return _index; }
set
{
if (_index != value)
_index = value;
}
}
instead of:
public int Index { get { return _index; } set { _index = value; } }
The other thing is that try catch exceptions are expensive, so instead of having:
try { i_percentage = double.Parse(t_percentage); } catch { }
because you know that if there is a value it is going to be a double, you can change it to:
if (!string.IsNullOrEmpty(t_percentage))
i_percentage = double.Parse(t_percentage);
now if you don't know if the value in t_percentage is going to be a double you can use a try-parse:
if (!string.IsNullOrEmpty(t_percentage))
double.TryParse(t_percentage,out i_percentage);
This way you avoid the overhead caused by an exception. This might be micro-optimizing and is not always neccessary if it doesn't actually cause a problem, but given that you can have hundreds of jobs, each with 10 or so properties refreshing everysecond, things can actually get noticeably slower if even 2 of the 10 properties throws an exception.
One more thing, after your backgroundworker is completed, in the method: dgvQueue_Update() you are calling the ResetBindings(true); this causes your whole datagrid to refresh instead of just the individual items.
try changing it to:
for (int i = 0; i < jobSource.List.Count; i++)
jobSource.ResetItem(i);
The difference is this:
this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, itemIndex));
compared to when you say ResetBindings:
this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));