代码之家  ›  专栏  ›  技术社区  ›  Jerry

C#数据绑定Windows窗体控件不会保留值,除非您离开该字段

  •  11
  • Jerry  · 技术社区  · 16 年前

    Databound Windows Forms control does not recognize change until losing focus

    但这并不能完全回答我的问题。我有完全相同的情况。在ToolStrip_单击时,我遍历了所有控件并强制执行“WriteValue()”,但它仍然恢复到保存前的值。有人能建议我如何解决这个问题吗?我执行得不正确吗?

    (请参阅当前(非工作)解决方案的代码。)

    private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
    {
        // Make sure that all items have updated databindings.
        foreach (Control C in this.Controls)
        {
            foreach (Binding b in C.DataBindings)
            {
                // Help: this doesn't seem to be working.
                b.WriteValue();
            }
        }
    }
    

    代码现在简单多了,但它是一个相当大的黑客。我很高兴知道是否有更“合适”的解决方案。

    private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
    {
        // Make sure that all text fields have updated by forcing everything
        // to lose focus except this lonely little label.
        label44.Focus();
    }
    
    6 回复  |  直到 9 年前
        1
  •  27
  •   Sheridan    10 年前

    问题可能是您的数据绑定控件设置为在验证时更新。

    您需要将每个数据绑定控件的DataSourceUpdateMode设置为DataSourceUpdateMode.OnPropertyChanged。例如,数据绑定文本框:

    this.textBox1.DataBindings.Add(new System.Windows.Forms.Binding("Text", 
        this.someBindingSource, "SomeProperty", true, 
        System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
    

    还可以通过以下方式在设计器中设置数据源更新模式:

    选择控件并转到属性窗口->(数据绑定)->((高级)

    干杯

        2
  •  3
  •   Henk Holterman    16 年前

        3
  •  3
  •   Peter Mortensen Pieter Jan Bonestroo    10 年前

    你和什么有关?如果是DataSet、DataTable等,或者更好的是BindingSource,则应调用EndEdit:

    private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
    {
        // Assuming that you are binding to bindingSource1:
        bindingSource1.EndEdit();
    }
    

    我实现了一个 ISave 我的窗体上的接口,用于处理脏状态并保存和 无论何时 选中脏状态(无论何时调用IsDirty),我总是在绑定源上重新编辑:

    interface ISave
    {
        bool IsDirty;
        bool Save(bool force);
    }
    

    有了这个接口,比如说,当应用程序关闭时,我可以轻松地遍历打开的MdiChild窗口,检查是否通过将子窗体强制转换为 以及检查 IsDirty . 这里,我在适当的绑定源或绑定控件(如适用)上调用EndEdit(例如,网格)。

    请原谅我的漫谈,但我认为这可能会有帮助。其余的工作原理如下:

    Save() 取一个参数“force”,这样我就可以有一个“Save&关闭“按钮”窗体(为用户保存一次额外的单击或确认,询问他们是否要保存更改)。如果force为false,则 保存()

    保存() 保存本身没有抛出错误。或 保存() 在用户选择的事件中返回false 取消 或者出现错误(换句话说,告诉调用代码取消表单关闭)。

    您如何处理错误取决于您的异常捕获约定-这可以在 保存() 方法,并向用户显示,或者在FormClosing之类的事件中显示 e.Cancel 然后将设置为true。

    与表单关闭事件一起使用时,它将如下所示:

    private void form1_FormClosing(object sender, CancelEventArgs e)
    {
        if (IsDirty)
            e.Cancel = !Save(false);
    }
    

    与save&中的强制保存一起使用;“关闭”按钮,它将如下所示:

    private void btnSaveAndClose_Click(object sender, EventArgs e)
    {
         if (IsDirty)
            if (Save(true))
                Close();
    }
    

    无论如何,比你要求的多一点,但我希望这有帮助!

        4
  •  0
  •   TheQult    16 年前

    试试这个:

    private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
    {
        // Make sure that all items have updated databindings.
        foreach (Control C in this.Controls)
        {
            C.SuspendLayout();
            foreach (Binding b in C.DataBindings)
            {
                // Help: this doesn't seem to be working.
                b.WriteValue();
            }
            C.ResumeLayout();
        }
    }
    
        5
  •  0
  •   Nate Cook    13 年前

    这在过去一直困扰着我。除了将DataSourceUpdateMode设置为OnPropertyChanged之外,数据源中的基础列不能是只读的。

    在数据表中检查您的列:

    dataTable.Columns("ColumnName").ReadOnly

    Public Function MakeReadOnlyFalse(ByVal dt As DataTable) As DataTable
    
        For Each col As DataColumn In dt.Columns
            If col.ReadOnly Then
                col.ReadOnly = False
            End If
        Next
    
        Return dt
    End Function
    
        6
  •  -1
  •   Michel P.    10 年前

    对我来说这是最糟糕的。如果我将更新源模式设置为OnPropertyChanged on combobox,它的行为就像我将其设置为Onvalidation模式一样!wpf中的绑定要好得多。