C# 提示用户保存DavaGridView_RowLeave上的当前行的消息

C# 提示用户保存DavaGridView_RowLeave上的当前行的消息,c#,winforms,events,datagridview,architecture,C#,Winforms,Events,Datagridview,Architecture,我有两个用户可编辑的DataGridView。 当用户在DataGridViewA中选择一行时,DatagridViewB将相应地填充不同的数据 在DataGridViewA中编辑当前行后,用户可以单击保存按钮。如果用户没有保存并在DataGridViewA中选择另一行,则会向用户提示一条保存消息,询问用户在移动到另一行之前是否要保存。(我有一种方法可以检查是否有更改,如果有,则在用户想要保存时提示消息-是:保存,否:恢复数据) 检查是否有更改的方法在DataGridViewA_Leave()上

我有两个用户可编辑的DataGridView。 当用户在DataGridViewA中选择一行时,DatagridViewB将相应地填充不同的数据

在DataGridViewA中编辑当前行后,用户可以单击保存按钮。如果用户没有保存并在DataGridViewA中选择另一行,则会向用户提示一条保存消息,询问用户在移动到另一行之前是否要保存。(我有一种方法可以检查是否有更改,如果有,则在用户想要保存时提示消息-是:保存,否:恢复数据)

检查是否有更改的方法在DataGridViewA_Leave()上触发。原因是在离开该行之前,我拥有DataGridViewA.CurrentRow的信息,以便在需要时进行保存

问题是,如果我正在单击表单上的任何其他控件(如“保存”按钮),则会将消息保存到用户提示(因为DataGridViewA.CurrentRow已保留)。在这种情况下,我不希望用户收到消息

我找到了解决办法,但我想这不是最好的办法。在提示消息之前,我正在检查保存按钮是否有焦点。需要对我不希望在单击时收到保存消息的所有控件执行此检查

有没有更好的办法来解决这个问题

我的代码,记录状态为添加(用户添加行)或编辑(用户更新某些数据):


我猜一旦用户在行级别单击编辑按钮,您就可以看到“保存”按钮,因此,当用户单击“编辑”按钮并突然离开该行时,您可以在AlternateDGV_RowLeave事件的行级别上检查“保存”按钮的可见性,如果它仍然可见,这意味着用户尚未单击“保存”按钮,您可以提示用户。

在我看来,您应该更改用于加载数据和管理网格的方法中的某些内容

如果使用DataGridViewA.SelectionChanged事件加载DataGridViewB中的数据,则应该能够检查未保存的更改,然后重新加载DataGridViewB内容

注意:SelectionChanged事件仅在所选行发生更改后才会触发,因此在DataGridViewB中加载行时,至少应保存当前所选行的索引,以便在选择新行时检查正确的行

例如:

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;
}
编辑:

另一个解决方案是检查网格是否仍然有焦点。如果没有,则用户在网格外单击,您无需提示消息

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);
                }
            }
        }
    }

DataGridView.LostFocus?你所说的DataGridView.LostFocus是什么意思?你考虑过使用LostFocus事件吗?你可以使用与RowLeave相同的方法使用它-也许它会更复杂…我认为你的“变通方法”是一个非常简单的解决方案-坚持它:)为什么不使用SelectionChanged事件而不是Leave?您可以将当前选定的行保存在局部变量中,当选择更改时,您会向用户提示消息,如有必要,还可以保存配置。我遗漏了什么吗?我想你指的是启用/禁用按钮(不可见)。我没有这样做,也没有帮助,因为如果用户离开该行单击“保存”按钮,我不想提示,但如果他离开该行选择另一行,我想提示。我真的理解你的意思,但我认为它可能有一个使用事件的解决方案。如此多的事件和如此简单的事情应该相应地解决,而不必除了DataGridView本身之外还要管理数据。谢谢我明白你在寻找什么,但我认为你应该把重点放在选择的改变上,因为假设用户点击的位置是处理问题的错误方法。考虑到当焦点位于DATAGIDVIEWA时,用户最终也可以通过使用箭头键来改变选择。在这种情况下,你想要的效果是什么?在这种情况下,row_enter被提升,这对我来说没问题。好吧,我添加了一个可能的不同解决方案,也许你已经尝试过了。这与我在帖子中写的解决方法非常相似。如果用户单击“保存”按钮,会发生什么情况?焦点将移动到按钮,而不是网格本身。
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);
                }
            }
        }
    }