【问题标题】:Ability to notify users to ask for 'Save Changes' when user tries to close the Windows Form without saving当用户尝试关闭 Windows 窗体而不保存时,能够通知用户请求“保存更改”
【发布时间】:2012-10-31 21:22:34
【问题描述】:

我正在使用 C# Windows Forms (.NET 3.5),并尝试在用户修改 Detail 表单上的任何数据有界列时实现该功能,并尝试在不保存的情况下关闭表单,系统应该弹出我的消息“保存更改?”。

我知道我总是可以将TextChanged 事件用于Textbox 等,但这需要多个事件编码。我想使用一个特定的事件处理程序来检测与我的BindingSource 关联的任何字段中的值变化。

我已经像这样限制了我的列:

textbox1.DataBindings.Add("Text", this.bindingSource1, "dbcolumn_1", true);

【问题讨论】:

    标签: c# winforms .net-3.5


    【解决方案1】:

    这样的东西有用吗?

    1. 在表单中定义一个 changedFlag 变量,默认值 = false。

      private changedFlag = false; // form value(s) changed, check it on form close

    2. 将其放入退出按钮的事件处理程序中,或适应表单关闭处理程序:

          if (this.changedFlag && MessageBox.Show("Save your changes before exit?", "Save changes?", MessageBoxButtons.OKCancel) == DialogResult.OK)
          {
              this.Save();
          }
      
    3. 创建一个函数,该函数接受一个控件容器并递归地查看其控件以连接更改处理程序(在步骤 4 中定义)。

      private void AddOnChangeHandlerToInputControls(Control ctrl)
      {
          foreach (Control subctrl in ctrl.Controls)
          {
              if (subctrl is TextBox)
              {
                  ((TextBox)subctrl).TextChanged += new EventHandler(InputControls_OnChange);
              }
              else if (subctrl is CheckBox)
              {
                  ((CheckBox)subctrl).CheckedChanged += new EventHandler(InputControls_OnChange);
              }
              else if (subctrl is RadioButton)
              {
                  ((RadioButton)subctrl).CheckedChanged += new EventHandler(InputControls_OnChange);
              }
              else if (subctrl is ListBox)
              {
                  ((ListBox)subctrl).SelectedIndexChanged += new EventHandler(InputControls_OnChange);
              }
              else if (subctrl is ComboBox)
              {
                  ((ComboBox)subctrl).SelectedIndexChanged += new EventHandler(InputControls_OnChange);
              }
              else
              {
                  if (subctrl.Controls.Count > 0)
                  {
                      this.AddOnChangeHandlerToInputControls(subctrl);
                  }
              }
          }
      }
      
    4. 创建一个设置 changedFlag = true 的通用更改处理函数

      private void InputControls_OnChange(object sender, EventArgs e)
      {
          this.changedFlag = true;
      }
      
    5. 一旦您的控件被构建(不确定您是否正在动态制作它们,但您在示例中使用了textbox1,所以我假设不是),从第 3 步调用该函数并传入输入的容器控制。

      AddOnChangeHandlerToInputControls(panelFormContainer);

    通过传入表单控件的容器,您可以避免手动连接每个控件的更改处理程序。并且记得修改Save()函数重置changedFlag = false;

    【讨论】:

      【解决方案2】:

      定义 on_closing 事件处理程序; http://msdn.microsoft.com/en-us/library/system.windows.forms.form.onclosing.aspx

      在其中启动一个表单,询问他们是否要保存并将其作为对话框打开,以便将焦点强制在该表单上(链接中的示例代码显示了如何执行所有这些操作)。

      【讨论】:

      • 感谢您的回复。我的表单中有大约 80 个字段,混合了 TextBox、Combobox、复选框等,它们都与 BindingSource 和 DataTable 相关联。我希望找到一个解决方案,我可以只处理 BindingSource 或 DataTable,而不是将每个字段与其在 on_closing 事件处理程序中的原始值进行比较,以检查是否有任何更改。谢谢。
      【解决方案3】:

      nothingIsNecessary 的答案非常接近,但我仍然需要环顾四周才能使其正常工作。

      也就是说,问题是

      AddOnChangeHandlerToInputControls(panelFormContainer);

      应该是

      AddOnChangeHandlerToInputControls(this);

      panelFormContainer 不起作用,我也找不到它的文档。

      参考:Loop through all controls on a form,even those in groupboxes

      我还继续添加了更多需要的控件类型。 我将 MouseCaptureChanged 用于 datePicker,因为复选框有时会触发 ValueChanged,有时不会。 ¯_(ツ)_/¯

      private void AddOnChangeHandlerToInputControls(Control ctrl) 
          {
              foreach (Control subctrl in ctrl.Controls)
              {
                  if (subctrl is TextBox)
                  {
                      ((TextBox)subctrl).TextChanged += new EventHandler(InputControls_OnChange);
                  }
                  else if (subctrl is CheckBox)
                  {
                      ((CheckBox)subctrl).CheckedChanged += new EventHandler(InputControls_OnChange);
                  }
                  else if (subctrl is RadioButton)
                  {
                      ((RadioButton)subctrl).CheckedChanged += new EventHandler(InputControls_OnChange);
                  }
                  else if (subctrl is ListBox)
                  {
                      ((ListBox)subctrl).SelectedIndexChanged += new EventHandler(InputControls_OnChange);
                  }
                  else if (subctrl is ComboBox)
                  {
                      ((ComboBox)subctrl).SelectedIndexChanged += new EventHandler(InputControls_OnChange);
                  }
                  else if (subctrl is MaskedTextBox)
                  {
                      ((MaskedTextBox)subctrl).TextChanged += new EventHandler(InputControls_OnChange);
                  }
                  else if (subctrl is DateTimePicker)
                  {
                      ((DateTimePicker)subctrl).MouseCaptureChanged += new EventHandler(InputControls_OnChange);
                  }
                  else if (subctrl is RichTextBox)
                  {
                      ((RichTextBox)subctrl).TextChanged += new EventHandler(InputControls_OnChange);
                  }
                  else if (subctrl is NumericUpDown)
                  {
                      ((NumericUpDown)subctrl).TextChanged += new EventHandler(InputControls_OnChange);
                  }
                  else
                  {
                      if (subctrl.Controls.Count > 0)
                      {
                          this.AddOnChangeHandlerToInputControls(subctrl);
                      }
                  }
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-16
        • 2011-07-22
        • 1970-01-01
        • 1970-01-01
        • 2020-03-03
        • 1970-01-01
        相关资源
        最近更新 更多