When the DataGridView in my application is populated, the following method is fired:
public void OrderSelectionChanged()
{
ConfirmOrCancelChangesDialog();
// Get values from selected order and populate controls
if (view.OrderTable.SelectedRows.Count != 0)
{
OrderViewObject ovm = (OrderViewObject)view.OrderTable.SelectedRows[0].DataBoundItem;
selectedOrder = orderModel.GetOrderById(ovm.OrderId);
// Populate view controls with data from selected order
view.OrderID = selectedOrder.Id.ToString();
---->> view.OrderDateCreated = selectedOrder.DateCreated; <<-----
view.OrderDeliveryDate = selectedOrder.DeliveryDate;
PopulateOrderAddressControls(selectedOrder.Address);
PopulateOrderItemTableControl();
PopulateOrderWeightAndSumControls();
view.OrderNote = selectedOrder.Note;
// Enable buttons
view.DeleteOrderButtonEnabled = true;
view.NewOrderItemButtonEnabled = true;
}
else
{
view.DeleteOrderButtonEnabled = false;
}
}
For some reason, the "isSaved" variable is being changed from true to false at the row I marked with arrows and I can't figure out why. This is not supposed to happen and was never an issue before, but suddenly appeared.
The variable "isSaved" is being checked in the following method:
public void ConfirmOrCancelChangesDialog()
{
if (!isSaved)
{
DialogResult dialog = MessageBox.Show(Properties.Resources.SaveChanges,
Properties.Resources.SaveChangesTitle, MessageBoxButtons.YesNo);
if (dialog == DialogResult.Yes)
{
SaveOrder();
}
else
{
UndoChanges();
}
}
}
This is causing the save or cancel dialog to appear everytime the application is started, which obviously is wrong. Since the selection changed method is fired three times and isSaved is changed during the first run, the dialog pops up during the second time around. Through debugging step by step I could figure out at what point isSaved is changing, but not how or why.
View is the form, OrderDateCreated is a getter/setter for a DateTimePicker, selectedOrder is just an order object and DateCreated a Date. Am I missing something here?
Cheers!
It seem related to your code setting values to view object.
If you didn't create properties by your own, that object may have set properties which detects any change and setting the isSaved properties to false.
Try this workaround:
bool wasSaved = isSaved; //reference properly to your isSaved variable, and store it in the wasSaved local var
view.OrderID = selectedOrder.Id.ToString();
view.OrderDateCreated = selectedOrder.DateCreated;
view.OrderDeliveryDate = selectedOrder.DeliveryDate;
isSaved = wasSaved; //revert to the previous state
Related
I am trying to use a ListView to pull in data from a database. It "works" on the first try if the value exists, but it has a problem when searching for values that don't and then trying again with any other value(even if that other value does exist).
When debugging, I noticed the following:
If I search for a value that doesn't exist in thedatabase, then try to search for one that does, the debugger goes from the line "bValid = true" directly to the method to get the data for the Listview (lstAuthorizations_GetData()). Instead it should go to bindData. It seems like its not processing the bValid = true line. Why would it break here? I've tried changing the line to other variations but no matter what it is, it doesn't seem to process in the right order
Code:
else //default
{
if(string.IsNullOrEmpty(Search_ANumber) && string.IsNullOrEmpty(Search_MemberID))
{
bValid = false;
errorMsg = "Either A Number or M ID are required";
}
else
{
bValid = true;
lstAuthorizations.FindControl("cColumn").Visible = false; // if not in ActiveExceptions, hide column //may want to move this to Line 214
}
}
if (bValid)
{
bindData();
}
protected void bindData()
{
//removeTextBoxValues(); //remove values from Textboxes since you got a response from the DB
ShouldSearch = true;
panelSearchResults.Visible = true;
lstAuthorizations.DataBind();
}
ListView's getdata method:
public IQueryable<Project.Data.databaseView> lstAuthorizations_GetData()
{
try
{
IQueryable<databaseView> query = dbVBA.databaseView.AsQueryable();
if (!String.IsNullOrEmpty(Search_AuthNumber))
{
query = query.Where(m => m.A_Number == Search_ANumber);
}
return query.OrderBy(a=>a.A_Number);
}
aspx:
<asp:ListView ID="lstAuthorizations" runat="server"
ItemPlaceholderID="litPlaceHolder"
ItemType="Project.Data.databaseView" SelectMethod="lstAuthorizations_GetData">
It seems to run the method to get data from the database twice when it actually returns a result (it goes to the lstAuthorizations_GetData() method, then it goes to data bind, then it goes to the lstAuthorizations_GetData() method again). In cases where I try a second value, it goes to the lstAuthorizations_GetData() method, but never goes to bind data.
Anyone know why this is failing?
I had to move hiding/displaying the control AFTER the data was binded. It works now:
if (bValid)
{
bindData();
lstAuthorizations.FindControl("cColumn").Visible = true;
I have a listview with a checkbox on each row and I need to make it so that if the user exits the app and later comes back to that liistview the same items remain checked, I have succesfully saved the checked items, but If I try to recheck them in the getview() method the list starts to lag, and random checkboxes start getting checked.
Below is my code that rechecks the boxes
using (VehicleFeaturesDB vfdb = new VehicleFeaturesDB())
{
selectedfeatures = vfdb.GetSelectedFeatures(Selector.vehicleId);
if (listOfSelectedFeatures != null)
{
foreach (Features f in listOfSelectedFeatures)
{
if (feature.FeatureID == f.FeatureID)
{
CheckBox.Checked = true;
}
}
}
}
Tha
If that using block is in GetView(), you're connecting to the database and pulling the list of features every time a new item is displayed. That's why you're seeing the lag.
You're also not setting Checked to false if the feature is not in the list, so when you reuse the convertview the checkbox may already be checked. That's why you're seeing the random boxes checked.
I would probably get the selected features in your adapter's constructor, then reference that list in your GetView(). Something like this should work for you.
public class MyAdapter...
{
private IEnumerable<SelectedFeature> selectedFeatures;
public MyAdapter()
{
...your code...
using (VehicleFeaturesDB vfdb = new VehicleFeaturesDB())
{
selectedfeatures = vfdb.GetSelectedFeatures(Selector.vehicleId);
}
}
public override View GetView(int pos, View convertView, ViewGroup parent)
{
...your code...
CheckBox.Checked = selectedFeatures.Any(sf => sf.FeatureID == feature.FeatureID);
}
I have a list of objects that I'm adding to.
private List<Employee> employees = new List<Employee>();
I have a button on my form application to create a new employee object and add it to the list. Prior to clicking it, it displays "Add Hourly Employee". After clicking it, it changes to "Save Hourly Employee". I'm just using a boolean to determine what text to display.
private void addHrlyEmpBtn_Click(object sender, EventArgs e)
{
resetBtn.Enabled = true;
cancelBtn.Enabled = true;
if (!addHourly)
{
resetBtn.Enabled = true;
cancelBtn.Enabled = true;
textBox4.Enabled = false;
textBox4.Text = (employees.Count + 1).ToString();
textBox7.Enabled = false;
addHrlyEmpBtn.Text = "Save Hourly Employee";
}
else if (addHourly)
{
//Grab values, create new object, and add to list.
//Set addHourly to false;
}
//Other stuff
}
I'm trying to display employees.Count + 1 to textBox4, but for some reason it isn't working. No text is being displayed at all. Idealy, I'd like to have the text box disabled but still display the value. And I only want it to display when !addHourly.
Am I doing something wrong?
There's nothing wrong in principal with the code you wrote.
I would strongly suggest giving meaningful names to all of your variables. Names like textBox4 are likely to cause confusion for yourself and future maintainers of the code.
If the value is not changing as you expect, you are most likely not entering that if branch.
Set a breakpoint at
if (!addHourly)
See if addHourly has the value you expect.
Check if addHrlyEmpBtn_Click is being called at all.
if it isn't try associating the Click event with addHrlyEmpBtn_Click method from the designer
or add addHrlyEmpBtn.Click += addHrlyEmpBtn_Click; in the constructor
I have created a messagebox which returns DialogResult. Now I added checkbox on it and want to know if it is checked or not. So what should I return? The simple way I thought is to create new enum which will have all the values from DialogResult plus a value to indicate checkbox status
public enum MyDlgResult
{
NONE = DialogResult.NONE,
OK = DialogResult.OK ........................,
CHKBOXCHECKED = 8
}
...and returning this enum MyDlgResult.
But is this correct approach? Because I have to add value in this enum every time a new functionality is added to my messagebox.
Better way to do this if any.
Thank You.
Just add Property to that message box, which will be a proxy to Checked property of CheckBox and on OK result form message box check that new Property.
Property to add
public bool Checked
{
get { return yourCheckBox.Checked; }
}
And final code like this
MessBox box = new MessBox();
if(box.Show() == DialogResult.OK)
{
bool isChecked = box.Checked;
}
You don't have to override the return of a dialog to enable the client code to get the state of a UI control. The dialog information is retained after it is closed and you can get values from it. For example, assume that there is a Form class named SomeDlg with a property called PublicDlgProperty. PublicDlgProperty can be set on OK, or any other UI change and then queried after the dialog is closed, like this:
var someDlg = new SomeDlg();
someDlg.ShowDialog();
var someLocalVariable = someDlg.PublicDlgProperty;
This is a very simple example. You'll need to test the DialogResult to see if you want to query the value or not.
I agree with both other people who answered you that you should have a property, delegating the IsChecked or something, but if you must do it using only the return enum result...
Make the enum Flagged:
[Flags]
public enum MyDlgResult
{
NONE = ...
OK = ...
CHK...
}
Then, you can return:
return MyDlgResult.NONE | MyDlgResult.CHK;
Or
return MyDlgResult.OK | MyDlgResult.CHK;
Or just
return MyDlgResult.OK;
And so on...
Then, you can check:
if (res.HasFlag(MyDlgResult.OK))
{
}
if (res.HasFlag(MyDlgResult.CHK))
{
}
I have a datagridview which we will call dataGridViewExample.
My object (the uncommon datatypes is because my database is SQLite):
class MyObject
{
public Int64 Vnr { get; set; }
public string Name { get; set; }
public Single Price { get; set; }
public int Amount { get; set; }
}
Here is the relevant code:
//This form gets called with a .ShowDialog(); in my form1.
private List<MyObjecte> ExampleList = new List<MyObject>();
public MyForm()
{
dataGridViewExample.DataSource = OrdreInkøbsListe;
}
private void AddtoDataGridViewExample()
{
//Add a new MyObject to the list
ExampleList.Add(new myObject()
{
Vnr = newVnr,
Amount = newAmount,
Price = newPrice,
Name = newName
});
//refresh datasource
dataGridViewExample.DataSource = null;
dataGridViewExample.Refresh();
dataGridViewExample.DataSource = OrdreInkøbsListe;
ddataGridViewExample.Refresh();
}
When MyForm gets called with a .ShowDialog, it shows up fine and displays my DataGridView example just fine. As you can read from the code, the ExampleListis initially empty, so it just shows an empty datagridview with 4 columns: Vnr, Name, Price & Amount. If I click inside it etc. nothing happens - so everything is working as planned, so far.
Everytime I call AddtoDataGridViewExample() it adds the new object to the Datagridview, and the datagridview does update, listing all the objects added so far (they show themself as rows, again according to plan).
Now, remember that I just said that nothing happened if you clicked inside DataGridViewExample before I have called AddtoDataGridViewExample()?
Well, after having called AddtoDataGridViewExample() once or more, the program will crash if I click inside DataGridViewExample (for example: the users wants to select a row). It throws an IndexOutOfRangeException and talks about an -1 index.
It also throws the exception in the other form, on the line where I call MyForm with .ShowDialog();
I really am stuck on this, do you guys have any idea what is wrong??
My only clue is that I do believe the refresh of DataGridViewExample's datasource might be the cause of the problem.
Another important note: I have yet bound any events to my DataGridViewExample. So you can rule that idea out.
Here is all DataGridViewExample's properties:
this.dataGridViewExample.AllowUserToAddRows = false;
this.dataGridViewExample.AllowUserToDeleteRows = false;
this.dataGridViewExample.AllowUserToResizeColumns = false;
this.dataGridViewExample.AllowUserToResizeRows = false;
this.dataGridViewExample.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dataGridViewExample.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridViewExample.Location = new System.Drawing.Point(591, 53);
this.dataGridViewExample.MultiSelect = false;
this.dataGridViewExample.Name = "dataGridViewExample";
this.dataGridViewExample.ReadOnly = true;
this.dataGridViewExample.RowHeadersVisible = false;
this.dataGridViewExample.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dataGridViewExample.ShowEditingIcon = false;
this.dataGridViewExample.Size = new System.Drawing.Size(240, 150);
this.dataGridViewExample.TabIndex = 31;
I guess the click event tries to get the currently selected row and do something with it, while dataGridViewExample.DataSource = null; clears the datasource, and the currently selected row becomes null.
If you set the DataGridView.DataSource to the list, you don't need to reset it to null, refresh, and reset it to the list again (and refresh again) to see the changes. It will be enough to just refresh the DataGridView.
You can also just try using an BindingList<T> object instead of a List<T>, which will automatically notify your grid of its internal changes (Adding and removing elements), and there's also an INotifyPropertyChanged interface you can implement on your MyObject class, that will make every property change in an object show on the grid (For any changes made to the object in the code, and not through the grid itself).
Have you tried running the debugger and break when InedxOutOfRangeException is thrown to see where the exception is thrown?
Select Debug > Exceptions then there's a Find button on the dialog so you don't have to browse through all of the possibilities.
I had similar situation. I assigned generic list of certain object to DataGridView. Then I was setting null to DataSource and after that refresh. After that I assign list of objects to DataSource. While clicked on grid while runtime error occured IndexOutOfRange. My solution was to assign new empty list of my object to that grid and refresh and after changes on my working list I do assign to DataSource and call Refresh. Now, it is working without any crashes. Please look on my code before:
grid.DataSource = null;
grid.Refresh();
if(cases.Count() > 0)
{
grid.DataSource = cases;
grid.Refresh();
}
And now on my code after:
grid.DataSource = new List<MyCase>();
grid.Refresh();
//do something with cases
if(cases.Count() > 0)
{
grid.DataSource = cases;
grid.Refresh();
}