Элемент управления Windows Forms с привязкой к данным C # не сохраняет значения, если вы не покинете поле - PullRequest
11 голосов
/ 11 января 2010

Я видел ответ в Элемент управления 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();
}

Ответы [ 6 ]

26 голосов
/ 04 ноября 2010

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

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

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

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

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

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

ура

3 голосов
/ 16 января 2010

С чем вы связаны? Если это 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», поэтому у меня может быть кнопка «Сохранить и закрыть» формы (сохраняет пользователю дополнительный щелчок или подтверждение, спрашивающее, хотят ли они сохранить свои изменения). Если force имеет значение false, метод Save() отвечает за запрос пользователя, хочет ли он сохранить. Если это правда, предполагается, что пользователь уже решил, что он определенно хочет сохранить свою информацию, и это подтверждение пропускается.

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

Способ обработки ошибок зависит от ваших соглашений о перехвате исключений - это может быть зафиксировано в методе 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();
}

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

3 голосов
/ 11 января 2010

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

0 голосов
/ 20 июля 2016

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

0 голосов
/ 12 декабря 2012

Это поставило меня в тупик в прошлом. В дополнение к тому, что 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
0 голосов
/ 12 января 2010

Попробуйте это:

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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...