【问题标题】:Any easy way to alert to changes in multiple text boxes?有什么简单的方法可以提醒多个文本框的变化?
【发布时间】:2016-03-11 21:28:58
【问题描述】:

我对编程很陌生,如果这很简单,我很抱歉,但我可能只是错过了明显的东西!我有以下表单,它会在加载时从存储在 INI 文件中的设置自动填充:

整个表格就像我希望它从一个小部分中分离出来一样工作。 “关闭”按钮当前只是关闭表单,因此如果自加载表单后文本框中的任何值发生更改,则更改将丢失。我想改为提示用户使用“保存”按钮,否则更改将丢失。

我一直在尝试在我的关闭按钮上按照这些行做一些事情,其中​​文本框的值与它们最初填充的变量值进行检查:

private void btnClose_Click(object sender, EventArgs e)
{
    if (txtName.Text != name || txtSchName.Text != schname || txtServer1.Text != svr1 etc etc etc)
    {
       Warn User changes will be lost, ask user if really OK to close?
       if (User chooses to to close)
       {
            this.Close();
       }
       else
       {
            Go back to the config form;
       }    
    }
    else
    {
        this.Close();
    }

拥有超过 21 个文本字段,我不确定这是否是检查更改的最“整洁的方式”?任何指针将不胜感激。

【问题讨论】:

  • Winforms? WPF?还有什么?
  • 如果你正确使用数据绑定而不是摆弄TextBox.Textdetecting a "dirty form" is trivial
  • @UweKeim 看起来像 WinForms,但它可能是别的东西
  • 对不起,我正在使用 Winforms。
  • 您可以使用属性绑定到应用程序设置。您可能会发现 this post 很有帮助。

标签: c# .net winforms


【解决方案1】:

您只需添加一个全局布尔变量并为 TextChanged 事件编写一个处理程序

// Declared at the form level
private bool _modified = false;

public Form1()
{
    InitializeComponent();

    // This could be done in the form designer of course 
    // o repeated here for every textbox involved....
    txtName.TextChanged += OnBoxesChanged;
    ......
}
private void Form1_Load(object sender, EventArgs e)
{
     .....
     // Code that initializes the textboxes could raise the TextChanged event
     // So it is better to reset the global variable to an untouched state
     _modified = false;
}
private void OnBoxesChanged(object sender, EventArgs e)
{
    // Every textbox will call this event handler
    _modified = true;
}
private void btnClose_Click(object sender, EventArgs e)
{
    if(_modified)
    {
         // Save, warning, whatever in case of changes  ....
    }

}

只需为要触发条件的每个文本框设置事件处理程序 OnBoxesChanged。您可以通过设计器或在 InitializeComponent 调用后手动完成

【讨论】:

  • 对每个文本框重复它对 OP 来说不是很麻烦吗?它仍然不是很可重用。如果 OP 有多种形式,他/她将不得不为所有形式做这件事
  • 嗯,当然,但是您可以完全控制哪个文本框或组合或列表或复选框或任何应该触发更改的选项。顺便说一句,我喜欢你的方法,但你应该添加一种方法来指定哪些控件触发 _isDirty 标志
  • 谢谢你,非常有见地!我只有这个需要检查的表格。我已经尝试过了,它就像我想要的那样工作!非常感谢。 :)
  • 也看看@kyle 的回答。它的代码是可重用的,尽管我认为我会添加一种方法来传递控件列表,而不是处理表单中的每个控件
【解决方案2】:

您正在寻找的是脏跟踪。脏跟踪用于跟踪控件的状态。这是一个简单的可重复使用的方法来跟踪您的控件

 public class SimpleDirtyTracker
 {

    private Form _frmTracked;  
    private bool _isDirty;


    public SimpleDirtyTracker(Form frm)
    {
      _frmTracked = frm;
       AssignHandlersForControlCollection(frm.Controls);
    }



     // property denoting whether the tracked form is clean or dirty
     public bool IsDirty
     {
       get { return _isDirty; }
       set { _isDirty = value; }
     }

      // methods to make dirty or clean
     public void SetAsDirty()
     {
       _isDirty = true;
     }


     public void SetAsClean()
     {
       _isDirty = false;
     }


     private void SimpleDirtyTracker_TextChanged(object sender, EventArgs e)
     {
      _isDirty = true;
     }

    private void SimpleDirtyTracker_CheckedChanged(object sender, EventArgs e)
   {
      _isDirty = true;
   }

     // recursive routine to inspect each control and assign handlers accordingly
   private void AssignHandlersForControlCollection(
   Control.ControlCollection coll)
   {
     foreach (Control c in coll)
    {
      if (c is TextBox)
          (c as TextBox).TextChanged 
            += new EventHandler(SimpleDirtyTracker_TextChanged);

      if (c is CheckBox)
          (c as CheckBox).CheckedChanged 
            += new EventHandler(SimpleDirtyTracker_CheckedChanged);

      // ... apply for other desired input types similarly ...

      // recurively apply to inner collections
      if (c.HasChildren)
          AssignHandlersForControlCollection(c.Controls);
  }
}

在你的主窗体中

  public partial class Form1 : Form
  {

    private SimpleDirtyTracker _dirtyTracker;



    private void Form1_Load(object sender, EventArgs e)
    {

      _dirtyTracker = new SimpleDirtyTracker(this);
      _dirtyTracker.SetAsClean();
    }

   private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
    // upon closing, check if the form is dirty; if so, prompt
    // to save changes
    if (_dirtyTracker.IsDirty)
    {
        DialogResult result
            = (MessageBox.Show(
                "Would you like to save changes before closing?"
                , "Save Changes"
                , MessageBoxButtons.YesNoCancel
                , MessageBoxIcon.Question));

     }

}

【讨论】:

【解决方案3】:

如果您想保存例如用户设置,您可以在属性中创建Settings

你可以像这样得到它们:

string anyProperty = WindowsFormsApplication1.Properties.Settings.Default.TestSetting;

您使用Save-方法保存它们:

WindowsFormsApplication1.Properties.Settings.Default.TestSetting = "Hello World";
WindowsFormsApplication1.Properties.Settings.Default.Save();

点击关闭按钮后可以调用Save-方法。

为了保存多个字符串属性,您可以创建System.Collections.Specialized.StringCollection 类型的属性,这样您就只创建一个属性而不是 21。

【讨论】:

    【解决方案4】:

    dirtytracer 的一个缺点是,即使更改恢复到原始状态,它也会返回“dirty”。如果您使用 DataContext 中的对象作为您的数据模型,所有这些任务都简化为:

    bool changed = dataContext.SomeTables.GetModifiedMembers(someRow).Any(); 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-22
      • 2019-10-30
      • 2011-09-23
      • 1970-01-01
      • 2011-09-04
      • 1970-01-01
      相关资源
      最近更新 更多