ASP.Net checkboxes and if statements - asp.net

I am asked to develop an application where a member can select 1 plan, a combination of plans, all plans, or none.
plan1, plan2, plan3, .... plan12
I ran the truth table to find out how many possibilities there are, and it turned out to be 4096. (Ridiculous!)
My plan was to write an if statement for each possibility like this:
if (plan1.Checked == true && plan2.Checked == false && ... && plan12.Checked == false){
// insert into into table test VALUES('Plan1')
}
and so on! Obviously, there must be a better and easier way than this. Any suggestions would help. Thank you all.

If you used a CheckBoxList or similar component this would be one approach.
CheckBoxList checkBoxList = ....; // Just an example here
// You would add the different project names into the CheckBoxList
String message = "";
for (int i = 0; i < checkBoxList.Items.Count; i++) // Look at every project name
{
if (checkBoxList.Items[i].Selected) // See if it's selected
{
message += checkBoxList.Items[i].Text; // Add the name to the message
}
}
Put message in DB; // <-- Store the message into your database here
Since you're only interested in selected items you wouldn't have to deal with non-selected items at all.
Note: There is probably a better/more efficient way of creating strings than this and you might be able to use lambda expressions. This is just showing a simple approach.

Andrew_CS answer is suitable and I prefer it, but here is another way:
Handle the checked event in the code behind of all checkboxes (use one event, but allow all checkboxes to be handled by it), and depending on the sender, then you can load the information you want.
It may be that you use a Select statement to load the relevant information for each checkbox during the checkbox checked event (might be a little easier to understand than a for loop!)

Related

VS windows forms

I was just wondering is there a less bloating and simpler way of clearing input elements say made up of text boxes, check boxes and combo boxes to a empty state, that being removing text from them etc. I have like maybe 50+ and was hoping of a tidier way of doing this.
Another scenario I have is a set of 18+ elements, each set having 2 text boxes and 2 check boxes, one being an 'enabled' check box that when selected will enable/disable its set. Would there be a way of creating a method to handle this and make the required changes rather than having to type out the same thing happening for each set?
if (cbEnhancedInputOptionEnabled1.Checked == true)
{
tbEnhancedInputOptionText1.Enabled = true;
tbEnhancedInputOptionInputID1.Enabled = true;
cbEnhancedInputOptionDefaultState1.Enabled = true;
}
else
{
tbEnhancedInputOptionText1.Enabled = false;
tbEnhancedInputOptionInputID1.Enabled = false;
cbEnhancedInputOptionDefaultState1.Enabled = false;
}
so I would have 18 of these just changing based on the number which correlates to the set. Each one being in their own cbEnhancedOptionEnabled_CheckedChanged event.
Is there a way of passing controls by reference to a method? that'll do the same as above but to the controls passed?
For the first scenario, you can create a method named, for example, ResetAllControls, where you can set the status of each control to its default state.
For the second scenario, you may implement CheckedChanged event for each checkbox to control what to be enabled/disabled.
Another option is to give prefixed name for each control in each set. For example, set1_txtBox, set2_ddl, etc. Then define a common method. The method should accept a parameter (based on the prefix or set order number) to decide which set that you want to enable/disable. In that method, you can loop through the list of controls of the Form and, based on the parameter, and enable/disable which controls that you wish. Finally, you can implement the CheckedChanged event for each checkbox that is responsible for enabling/disabling each set's status. In each CheckedChanged method, you call the common method and pass your parameter.
Let me know if these help you.

What is the best way to hide "Completed or Cancelled Items" in a table?

So I have setup a model/table that users will use as a project task list. I would like it so that when they change the Status (a field in the model) of an item to either Completed or Cancelled it is hidden.
That way they are only dealing with active entries. But I would also like them to be able to view these hidden (archived) items if needed.
I added the following code to the onAttach option of the table
var datasource = app.datasources.Projects;
datasource.query.filters.Status._notContains = 'Completed';
datasource.load();
And then I have a button with the following code so they can see hidden/archived items:
widget.datasource.query.clearFilters();
widget.datasource.load();
app.closeDialog();
var datasource = app.datasources.Projects;
datasource.query.filters.Status._contains = 'Completed';
datasource.load();
It works, but I feel like there might be a better/more elegant way to accomplish this. Especially since it looks like the app has to load then data, THEN filter it (which results in a slower load). (I think I might have some redundant code in there as well)
Also I feel like I am missing something with my syntax, because I can't get it to filter out Completed AND Cancelled.
Thank you for your help!
If you have a single page of items in the table and there aren't many items, then you can filter on the client side. For example, you can use a binding expression to add a "projectHidden" style to the row based on some logic and then use CSS to change the visibility of the row.
For your second code block, there is no reason to clear filters, load, set the filters and then load again. Just clear the filters, set the new filter, and call load. Also if you are manually controlling the query load, then you might want to uncheck the setting in the data source to automatically load data.
var datasource = app.datasources.Projects;
datasource.query.filters.Status._notEquals = 'Completed';
datasource.query.filters.Status._notEquals = 'Cancelled';
datasource.load();

objective-c if-else statement

I have both a UITextLabel and a UITextView occupying the same real estate, point-for-point in my view. I have an NSMutableArray allocated to populate the UITextLabel based on what the user taps in a table. I would also like to program the app to use the UITextView if and only if the user taps on one specific row. I think this can be accomplished with an if-else (if) statement, but I'm not sure. If that will work, I don't know what to put in the if part. So far, I have this:
if (qux == ??) {
fooTextView.text = textString;
} else {
fooTextLabel.text = textString;
}
I don't know what to set the if statement to. I tried to set it to
if (qux == the really long code containing the single array statement
I want displayed as a UITextView)
but that returned an error. Does anyone have a suggestion on how to get Xcode to recognize my single NSMutableArray table cell with the UITextView and not (also) with the UILabel? As of right now, the app builds but displays the text both in the UITextView, so it scrolls and does exactly what I want but also displays in the UILabel and is static and visible "underneath" the scrolling UITextView.
Also, I'm using an NSMutable Array with initWithObjectAndKeys. In this special case that is the only one of its kind in my UITableView, I use a special key that is only used by this particular part of the array. Is it possible to set it up so it's something regarding:
if (qux == *NSMutableArray with the special key*) {
fooTextView.text = textString;
} else {
fooTextLabel.text = textString;
}
And should I be using an if-else if statement or just an if-else statement?
Use the UITableView Delegate method didSelectRowAtIndexPath: you can get you row index from the NSIndexPath (indexPath.row). The you can use an if-then or a switch to determine which of your controls gets the data. Make sure you set your UITableView's delegate property to your file owner so the UITableView will call back to you controller.
HTH

Slow running web page

i created web page with dropdownlist and two gridview and on selectedindex changed event i fill the both of these gridview but in the running the both of gridview take long time to be filled.
Note:one of this gridview i created its datasource by code.
here my code snippet:
protected void _ddlPLCs_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable dtStatus = new DataTable();
dtStatus = DBLayer.getMachineNameIPStatusPlCByName(_ddlPLCs.SelectedValue);
dtStatus.Columns.Add("Status", typeof(String));
foreach (DataRow row in dtStatus.Rows)
{
if (LogicLayer.checkmachineStatus(row["machineIP"].ToString()))
row["Status"] = "Online";
else
row["Status"] = "offline";
}
GVStatus.DataSource = dtStatus;
GVStatus.DataBind();
if (_ddlPLCs.SelectedValue.Contains('-'))
{
_dsPLCs.SelectParameters.Clear();
_dsPLCs.SelectParameters.Add("PLCID","0");
_dsPLCs.DataBind();
}
else
{
_dsPLCs.SelectParameters.Clear();
_dsPLCs.SelectParameters.Add("PLCID", DBLayer.getPlCIDByName(_ddlPLCs.SelectedValue).ToString());
_dsPLCs.DataBind();
}
}
pleas help me
Looking at the code, I think the problem is in this method:
LogicLayer.checkmachineStatus()
I have a hunch that this actually makes a network request to remote machines/devices to determine their status. This is going to be slow, especially if you have machines that might not be online and you have to wait for them to timeout.
If this is the culprit, what you want to do instead is build a service that runs on your server. The service should continually make these checks in the background and update a database table with the results. You probably want to include a timestamp for the last check in the table. It might even be worth inserting rather than updating, so that you have history of when status's were at different values. Your ASP.Net code should then just show the database table.
Profile! Get a trial version of RedGate ANTS and run it against your code.
If you choose line level timings, it will put a number next to each line in the code that will tell you exactly how long each line takes as a % or in milliseconds. Make sure to use wall clock time not cpu time or wait time from your datasource won't be counted properly.
I'd bet your datasource is slow.
You're doing a lot of work here...
A few random thoughts
Networks can be slow -- #Joel had a good point on that one.
One thing to check would be postback -- make sure you're only databinding on selected index changed.
Why aren't you using a 'handles' caluse in your function? Might not be a problem, just curious.
If you change your "status" column header to "online", and then use checkboxes (checked = online, unchecked = off-line, or something like that, you'll just be updating a bool value for each row, instead of a string value.
Something looks odd about how you're re-binding your dropdownlist. Because... You're using the selected value as a parameter in the gridview. Then you're subsequently re-binding the dropdown list, which potentially will result in a different selected value. Which could be causing your gridview to be databound yet again in a circuit. Not sure, as I can't see all of your code.
Anyway, FWIW. Good luck.

"EntityCollection already initialized" error with entity as model in Asp.Net MVC?

I'm having great difficulties with creating a complex object. I have an EF model with a Consultant table that has one-to-many relationships to a number of other tables. I wanted to use the Consultant object as the model as is because it would be very simple and easy (and as it's done in the NerdDinner tutorial), as I've done with other objects that didn't have one-to-many relationships. The problem is that these relationships cause this error: "EntityCollection already initialized" when I try to post to the Create method.
Several people have advised me to use a ViewModel instead, and I posted a question about this (ViewModels and one-to-many relationships with Entity Framework in MVC?) because I don't really understand it. The problem is the code gets reeeeally ridiculous... It's a far cry from the simplicity I've so far appreciated in MVC.
In that question I forgot to mention that besides the Create method, the Edit method uses the same CreateConsultant method (the name may be misleading, it actually populates the Consultant object). And so in order not to have additional, say "Programs" added when editing, I needed to complicate that method further. So now it looks like this:
private Consultant CreateConsultant(ConsultantViewModel vm, Consultant consultant) //Parameter Consultant needed because an object may already exist from Edit method.
{
consultant.Description = vm.Description;
consultant.FirstName = vm.FirstName;
consultant.LastName = vm.LastName;
consultant.UserName = User.Identity.Name;
if (vm.Programs != null)
for (int i = 0; i < vm.Programs.Count; i++)
{
if (consultant.Programs.Count == i)
consultant.Programs.Add(vm.Programs[i]);
else
consultant.Programs.ToList()[i] = vm.Programs[i];
}
if (vm.Languages != null)
for (int i = 0; i < vm.Languages.Count; i++)
{
if (consultant.Languages.Count == i)
consultant.Languages.Add(vm.Languages[i]);
else
consultant.Languages.ToList()[i] = vm.Languages[i];
}
if (vm.Educations != null)
for (int i = 0; i < vm.Educations.Count; i++)
{
if (consultant.Educations.Count == i)
consultant.Educations.Add(vm.Educations[i]);
else
consultant.Educations.ToList()[i] = vm.Educations[i];
}
if (vm.WorkExperiences != null)
for (int i = 0; i < vm.WorkExperiences.Count; i++)
{
if (consultant.WorkExperiences.Count == i)
consultant.WorkExperiences.Add(vm.WorkExperiences[i]);
else
consultant.WorkExperiences.ToList()[i] = vm.WorkExperiences[i];
}
if (vm.CompetenceAreas != null)
for (int i = 0; i < vm.CompetenceAreas.Count; i++)
{
if (consultant.CompetenceAreas.Count == i)
consultant.CompetenceAreas.Add(vm.CompetenceAreas[i]);
else
consultant.CompetenceAreas.ToList()[i] = vm.CompetenceAreas[i];
}
string uploadDir = Server.MapPath(Request.ApplicationPath) + "FileArea\\ConsultantImages\\";
foreach (string f in Request.Files.Keys)
{
var filePath = Path.Combine(uploadDir, Path.GetFileName(Request.Files[f].FileName));
if (Request.Files[f].ContentLength > 0)
{
Request.Files[f].SaveAs(filePath);
consultant.Image = filePath;
}
}
return consultant;
}
This is absurd, and it's probably due to my incompetence, but I need to know how to do this properly. Just the answer "use a ViewModel" obviously won't suffice, because that's what got me into this trouble to begin with. I want the simplicity of the simple entity object as model but without the "EntityCollection has already been initialized" error. How do I get around this?
Of course, if I'm just doing the ViewModel strategy the wrong way, suggestions on that are welcome too, but mainly I want to know what is causing this error if I do it the simple "NerdDinner" simple object way. Please keep in mind also that the View in question is restricted to authorized users of the site. I would love to do it the "correct" way, but if using ViewModels implies having code that is this hard to maintain, I'll forgo it...
Please help!
UPDATE:
Turns out this code doesn't even work. I just checked after calling Edit to update values, and it doesn't update them. So only the Create part works.
This is the part that doesn't work:
consultant.Programs.ToList()[i] = vm.Programs[i];
I sort of had a hunch I couldn't use ToList and update an item in the EntityCollection. But this makes it even harder. So now I don't know how to do it with the entity directly, which I would prefer (see above). And I don't know how to get this ViewModel stuff working, let alone get it clean...
Any ideas? There must be something really wrong here, and I'm hoping someone will spot how I've just missed something simple that turns all of this code on its head!
Ok, so in my experience the EF stuff doesn't easily play nicely when used on the wire, full stop (meaning, it's not a good format for passing data in whether you're in MVC or WCF, or whatever). It's an EF issue, to me, not a MVC issue because the problem you're experiencing with the direct use of your EF models has to do w/ how they're tracked in the EF objectcontext. I've been told that there's solutions to that involving re-attaching the passed entity, but I've found it to be more trouble than it's worth; as have others which is why most folks say "use viewmodels" for your input parameters in this situation.
I agree that your code above is kind unpleasant, there's a couple ways to fix it. First, check out AutoMapper, which helps a lot in that you can skip defining the obvious (e.g. when both models have a simple property like "Name" of hte same type & name.
Second, what you're doing w/ the loops is a bit off anyway. You should not assume that your list being posted from the client is the same order, etc as the list that EF is tracking (lists, rather; referring to your Programs, etc). Instead, think of the scenarios that might occur and account for those. I'll use Programs as an example.
1) a consultant has a program, but details about that program have changed.
2) a consultant does not have a program that is in the viewmodel
2a) the program already exists in the database somewhere, just not part of this consultant
2b) the program is new.
3) a consultant has a program that's not in the viewmodel (something you don't currently account for).
I don't know what you want to have happen in each of those cases (i.e. is the viewmodel complete and canonical, or is the entity model, during an update?), but let's say you're looping over your viewmodel's Programs as you do above. For the scenario 1 (which seems to be your main problem), you will want to do something like (using AutoMapper):
var updated = vm.Programs[i];
var original = consultant.Programs.SingleOrdefault(p=>p.ID == uppdated.ID);
Mapper.Map(updated,original);
yourEfContext.SaveChanges(); // at some point after this, doesn't have to be inside the loop
EDIT:
one other thought that might be useful to you is that I when you fetch your consultant out of the database (not sure what mechanism you use for that), make sure you call Include on the collections that you're going to update as well. Otherwise, each of those iterations you do will be another round-trip to the database, which obviously you could avoid if you just used Include to eager-load them all in one shot.

Resources