Prompting message to user to Save the current row on DavaGridView_RowLeave - c#

I have two DataGridViews with editable by the user.
When the user select a row in DataGridViewA then DatagridViewB is populated with different data accordingly.
Once edited the current row in DataGridViewA, the user can click on the save button. In case he didn't save and select another row in DataGridViewA, a message for save will be prompted to the user asking him if he want to save before moving to another row. (I have a method that check if there are changes and if yes, prompt a message to the user if he wants to save - yes: Save, No: Restore Data).
The method that checks if there are changes is triggered on DataGridViewA_Leave(). The reason is that I have the information of the DataGridViewA.CurrentRow before leaving the row so I can Save if needed.
The problem is if I am clicking on any other control on my form such as Save button the Save message to the user prompt (because the DataGridViewA.CurrentRow is left). In this case, I do not want the user to get a message.
I found a workaround to fix it but it is not the best way to do it I presume. Before prompting the message, I am checking if the Save button has focus. This check need to be done for all the controls that I don't want to get a Save message when clicking on them.
Is there any better solution to solve this issue?
My code, the record state is Added (user add a row) or Edited (user update some data) :
private void AlternateDGV_RowLeave(object sender, DataGridViewCellEventArgs e)
{
if (IsSaveNeeded)
{
if (SaveButton.Focused) // This is the work around
{
return;
}
if (!WasSavedPerUserRequest())
{
var recordstate = AlternateDGV.CurrentRow.Cells[Glossary.RecordStateName].Value.ToString();
if (recordstate == Glossary.AddedRecordState) // if it was a new row added and the user doesn't want to save
{
AlternateDGV.CurrentRow.Delete();
}
else if (recordstate == Glossary.EditedRecordState) // if it was a row from DB and the user doesn't want to save, refresh with saved data
{
AlternateDGV.CurrentRow.Refresh(_items);
}
}
}
}

In my opinion, you should change something in the method you use to load data and manage the grid.
If you load the data in DataGridViewB using the DataGridViewA.SelectionChanged event, you should be able to check for unsaved changes and then reload the DataGridViewB content.
NOTE: SelectionChanged event is fired only after the selected row is changed, so you should at least save the index of the current selected row when loading the rows in DataGridViewB, so you can check the correct row when a new row is selected.
For example:
void DataGridViewA_SelectionChange(object sender, EventArgs e)
{
if (previousSelectedIndex != -1)
{
//Check for changes end if necessary prompt the message
[...]
}
//Load data in DataGridViewB
[...]
previousSelectedIndex = dataGridViewA.SelectedRows[0].Index;
}
EDIT:
Another solution could be to check if the grid still has the focus. If it has not, then the user clicked outside the grid and you don't have to prompt the message.
private void DataGridViewA_RowLeave(object sender, DataGridViewCellEventArgs e)
{
if (IsSaveNeeded)
{
if (dataGridViewA.Focused == false)
{ //DataGridViewA without focus, then nothing to do
return;
}
if (!WasSavedPerUserRequest())
{
var recordstate = AlternateDGV.CurrentRow.Cells[Glossary.RecordStateName].Value.ToString();
if (recordstate == Glossary.AddedRecordState) // if it was a new row added and the user doesn't want to save
{
AlternateDGV.CurrentRow.Delete();
}
else if (recordstate == Glossary.EditedRecordState) // if it was a row from DB and the user doesn't want to save, refresh with saved data
{
AlternateDGV.CurrentRow.Refresh(_items);
}
}
}
}

i guess you make visible 'Save' button once User click on Edit button at row level , So when user click on edit button and suddenly leave the row you can check visibility of save button at row level on your AlternateDGV_RowLeave event if it is still visible that means that user has not clicked the save button yet and you can prompt user.

Related

Prevent first cell of DataGridView from being selected when row header clicked

I need to allow the user to select a row by clicking on the row header to allow row deletion, but when the row header is clicked, the first cell gets focus and the text is highlighted, which I need to prevent so the user can't make accidental edits to that first cell.
Here's an example of what's happening:
As you can see, the first cell has focus and the user can edit that cell, when all that was done was the row header was clicked.
I tried the answer to this SO question, but neither event fired when I clicked a row header. Here's the code that I used for that attempt:
private void dgvCategories_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
{
if (e.StateChanged == DataGridViewElementStates.Selected)
{
Console.WriteLine("true");
dgvCategories.ReadOnly = true;
}
}
private void dgvCategories_CellStateChanged(object sender, DataGridViewCellStateChangedEventArgs e)
{
if (e.StateChanged == DataGridViewElementStates.Selected)
{
Console.WriteLine("false");
dgvCategories.ReadOnly = false;
}
}
I also tried experimenting with the various DataGridViewEditMode options, but none of those accomplished what I need.
The DGV SelectionMode is set to RowHeaderSelect.
I still need to be able to grab the hidden "id" field in the row for the delete process. Here's my code for that:
private void btnDeleteRow_Click(object sender, EventArgs e)
{
int index = dgvCategories.SelectedRows[0].Index;
string rowId = dgvCategories[0, index].Value.ToString();
string deleteString = string.Format("DELETE FROM masterfiles.xref WHERE id = " + rowId);
conn.Open();
NpgsqlCommand deleteCmd = new NpgsqlCommand(deleteString, conn);
deleteCmd.ExecuteNonQuery();
conn.Close();
}
That works; I just need to prevent that first cell from automatically getting focus for editing when the row is selected. I still need to allow the user to select individual cells for editing, as well.
Try :
1- make the DataGridView selection by one row instead of one cell .
2- Disable allowing user to edit the DataGridView.
3- Make DataGridView ReadOnly .
Do 1 & 2 all the time except at editing operation .

Bindingsource won't update after the textbox Conrol updates

I have a form which its controls are binded to a bindingsrource named "userbindingsource". When the form loads all the value in bindingsrource will be set to equivalent Textbox. But when the textboxes values change , the bindingsrource won't update. and still it shows the very first value
For example after load I change the first name in textbox and then click save Button to call the saveRecord(). when I check (userBindingSource.DataSource as User) , it still contains the first firstname without any changes.
public void SaveRecord()
{
int i = 0;
User user = userBindingSource.DataSource as User;
if (user.Id > 0)
user.State = State.Modified;
using (ECarServiceClient client = new ECarServiceClient())
{
i = client.SaveUser(user);
}
}
how can make the bindingsource updates automatically?
If the textbox binding has DataSourceUpdateMode.OnValidation (the default) and you go right from typing in a textbox to clicking the Save button, the Save click is handled before the textbox validates. Validation is what makes the BindingSource update the User object.
The fix would be to call this.Validate() at the beginning of SaveRecord. This triggers validation of the focused control within the current form and all its ancestors.

Remember checked checkboxes in DataGridView

I have a DataGridView where the first column is a DataGridViewCheckBoxColumn. The user checks some checkboxes to indicate which items are to be deleted.
When I hide the form and reload it, I need the DataGridView to remember which checkboxes were checked.
You need to save the changes at least at the point where you close your Form (if you just hide it, why reload then?).
The way I usually work this out is listening to the Dgv's CellEndEdit event:
SomeDataGridView.CellEndEdit += ObjectPropertyChanged
then in the Callback you can get the Object back by using the "DataBoundItem" prop of the Dgv and process / save it however you need:
protected virtual void ObjectPropertyChanged(object sender, DataGridViewVellEventArgs e)
{
var selectedObject = ((DataGridView)sender).Rows[e.RowIndex].DataBoundItem;
//Assuming you stored in a List and each Object has an ID as prop:
var indx = _Objects.IndexOf(_Objects.Where(o => o.ID.Equals(selectedObject.ID)))
_Objects.Remove(indx)
_Objects.Insert(indx, selectedObject)
}
You could also do database update, write to a text-file, save in configuration, ...

Grid view Edit and save to database Winform

For a windows application, I have a form with a gridview. In the form, I have an Edit button. If the user selects one row and clicks on Edit, it has to redirect to another form with the selected data. The user can then enter details in that. When the user clicks on Save Data, it should save and go back to the database.
FIRSTListForm
private void btnNewFIRSTList_ItemClick(object sender, ItemClickEventArgs e)`
{
FIRSTEditForm FIRSTEditForm = new FIRSTEditForm(FIRSTID);`
FIRSTEditForm.Show();
}
private void btnEditFIRSTList_ItemClick(object sender, ItemClickEventArgs e)
{
//I need to know which row I selected before to Edit button
//object IdFirst = ((GridView)sender).GetRowCellValue(e.RowHandle, "IDFIRST");
//I need like a GetRowCellValue
FIRSTEditForm.Show();
}
You need a save method to write your data back to your database and call it on your save button click
Here is multiple examples of exactly what your wanting
if you want to open a separate form then youll need something like This
If you're using Datasets with winforms you can try:
1)Check if your gridview has any selected rows first
if (gridView1.SelectedRowsCount > 0)
{
......
}
2) If that's the case using strongly named DataRow class and BindingSource.Current:
YoutDataSet.YourTableOrResultSetRow Row;
var P = YourTableOrResultSetBindingSource.Current as DataRowView;
Row = (P.Row as YoutDataSet.YourTableOrResultSetRow );
int id = Row.ColumnNameThatContainstheID; //this will give you the ID you're after
Try it sir,
private void gridView_DoubleClick(object sender, EventArgs e)
{
if (gridView.GetFocusedRow() == null) return;
if (gridView.GetFocusedRowCellValue("ID") == null) return;
string id = gridView.GetFocusedRowCellValue("ID").ToString();
FIRSTEditForm frm = new FIRSTEditForm(id);
frm.Show();
}
In FIRSTEditForm use got ID and bind all your controls and save to database.
I use gridView_DoubleClick instead of your btnEditFIRSTList_ItemClick.
Hope it solves!

Datagrid Selection Changed Method

Currently I am trying to write a method to let user click on any datagrid cell or row in the datagrid view and after clicking information from datagrid view appers in the various textboxes / combo boxes. The thing is after clicking on the item it just doesn't work. Last time I when I wrote something else it was datagrid multiselect option which set to ture and caused problems, this time I have no idea what I did wrong. Method itself:
private void dataGridView3_SelectionChanged(object sender, EventArgs e)
{
foreach (DataGridViewRow row in this.dataGridView3.SelectedRows)
{
Group selectedGrp = row.DataBoundItem as Group;
if (selectedGrp != null)
{
this.textGrpID.Text = selectedGrp.GrpID;
this.textGrpName.Text = selectedGrp.GrpName;
this.comboBoxGrp.SelectedValue = selectedStd.StdGrp;
}
}
}
You want to show the textboxs for enter the the free text while clicking the row on datagrid. do u use the Edit template for showing the textbox and dropdown?
Why use the SelectionChanged event then? You didn't mention anything about changing selections... you said the user would click on a cell to see this information... so why not handle the Click event instead?

Categories

Resources