С# Бит данных Управление Windows Forms не сохраняет значение, если вы не покинете поле

Я видел ответ в Элемент управления Windows Forms с привязкой к базе данных не распознает изменения до потери фокуса.

Но это не полностью отвечает на меня. У меня такая же ситуация. На ToolStrip_click я просматриваю все свои элементы управления, и я принудительно нажимаю "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();
}

Ответ 1

Вероятно, проблема заключается в том, что ваши средства управления данными привязаны к обновлению при проверке.

Вам необходимо установить DataSourceUpdateMode каждого из элементов управления данными в DataSourceUpdateMode.OnPropertyChanged. Например, текстовое поле с привязкой к базе данных:

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

Вы также можете установить режим обновления источника данных в конструкторе:

Выбор элемента управления и переход в окно свойств → (DataBindings) → (Дополнительно)

- > Установите [Режим обновления источника данных] в раскрывающемся списке на OnPropertyChanged.

веселит

Ответ 2

Инструмент ToolStripButton не принимает фокус при нажатии. Вы можете добавить некоторый код, чтобы (временно) сфокусировать другой элемент управления. Вы можете сфокусировать ярлык (как нейтральный манекен).

Ответ 3

К чему вы привязаны? Если это DataSet, DataTable и т.д., Или еще лучше, BindingSource, вы должны вызвать EndEdit:

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

Я реализую интерфейс ISave для своих форм для обработки грязного состояния и сохранения и , когда проверяется состояние грязной (всякий раз, когда вызывается IsDirty), я всегда EndEdit на моем источнике привязки:

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

С этим интерфейсом, когда, скажем, приложение закрывается, я могу легко выполнить итерацию через открытые окна MdiChild, чтобы проверить, сохранена ли какая-либо информация, отбрасывая дочернюю форму ISave и проверяя значение IsDirty. Здесь я называю EndEdit либо соответствующим источником привязки, либо, если применимо, элементом управления привязкой (например, сеткой).

И прощай, но я подумал, что это может быть полезно. Остальное работает так:

Save() принимает параметр "force", поэтому я могу создать форму "Сохранить и закрыть" (сохраняет пользователю дополнительный клик или подтверждение, спрашивая, хотят ли они сохранить их изменения). Если сила ложна, метод Save() отвечает за запрос пользователя, хочет ли он сохранить. Если это правда, предполагается, что пользователь уже решил, что определенно хочет сохранить свою информацию, и это подтверждение пропущено.

Save() возвращает bool-true, если безопасно продолжать выполнение кода вызова (предположительно событие Form_Closing). В этом случае (если сила была ложной), с учетом YesNoCancel MessageBox, пользователь либо выбрал Yes, либо No, и само сохранение не выдало ошибку. Или, Save() возвращает значение false в случае, если пользователь выбрал Cancel, или произошла ошибка (другими словами, сообщение вызывающему коду для отмены закрытия формы).

Как вы обрабатываете ошибки, зависит от ваших исключающих соглашений - это может быть либо уловлено в методе Save(), либо отображаться пользователю, либо, возможно, в событии, таком как FormClosing, где e.Cancel будет установлено значение true.

Используется с событием закрытия формы, это будет выглядеть так:

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

Используется с принудительным сохранением с помощью кнопки "Сохранить и закрыть", это будет выглядеть так:

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

В любом случае, немного больше, чем вы просили, но я надеюсь, что это поможет!

Ответ 4

Попробуйте следующее:

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

Это в тупик меня в прошлом. В дополнение к DataSourceUpdateMode, установленному в OnPropertyChanged, базовый столбец в источнике данных не должен быть доступен только для чтения.

Проверьте его для столбца в DataTable:

dataTable.Columns("ColumnName").ReadOnly

Я даже сделал функцию, которая устанавливает, что все столбцы не являются 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

Для меня это хуже всего. Если я установил режим источника обновления OnPropertyChanged в combobox, он будет вести себя так же, как если бы я установил это в режим Onvalidation! Привязки намного лучше в wpf.