2009-10-28 28 views
7

Se si disattiva l'aggiornamento automatico di un'origine dati di binding impostando DataSourceUpdateMode = Never e quindi si utilizza un pulsante per aggiornare l'intero lotto (utilizzando binding.WriteValue), si verifica un problema - Vale a dire, solo il primo l'origine dati del controllo associato viene aggiornata. Tutti gli altri controlli vengono ripristinati sui valori originali.Associazione dati manuale utilizzando WriteValue

Questo perché quando l'oggetto corrente cambia (come accade dopo il precedente valore WriteValue), se ControlUpdateMode = OnPropertyChange, tutti gli altri controlli rileggeranno il valore dall'origine dati.

Qual è il metodo standard per evitare questo problema?

Un modo è quello di derivare una classe da BindingSource e aggiungere un metodo WriteAllValues. Questo metodo esegue le seguenti operazioni:

(1) Per ogni Binding, salvare il ControlUpdateMode

(2) Per ogni associazione, impostare ControlUpdateMode = Mai

(3) Per ogni Binding, chiamare il WriteValue metodo

(4) per ogni Binding, reimpostare ControlUpdateMode al valore memorizzato

(5) per ogni Binding, se ControlUpdateMode = onPropertyChange, chiamare il metodo ReadValue.

Riesci a vedere qualche problema con questo?

Se si lavora con le proprie classi, l'implementazione di IEditableObject risolve il problema?

In un altro controllo su cui sto lavorando, implemento il mio binding. Il modo in cui risolvo il problema è con il seguente codice. (Ho messo nel minimo indispensabile, spero che tu possa seguirla!):

Private Shared ControlDoingExplicitUpdate As MyCustomControl = Nothing 

Private Sub UpdateDataSourceFromControl(ByVal item As Object, ByVal propertyName As String, ByVal value As Object) 
    Dim p As PropertyDescriptor = Me.props(propertyName) 
    Try 
    ControlDoingExplicitUpdate = Me 
    p.SetValue(item, value) 
    Catch ex As Exception 
    Throw 
    Finally 
    ControlDoingExplicitUpdate = Nothing 
    End Try 
End Sub 

Private Sub DataBindingSource_CurrentItemChanged(ByVal sender As Object, ByVal e As System.EventArgs) 
    If (ControlDoingExplicitUpdate IsNot Nothing) AndAlso (ControlDoingExplicitUpdate IsNot Me) Then Exit Sub 
    Me.UpdateControlFromDataSource() 'Uses ReadValue 
End Sub 

Così, quando UpdateDataSourceFromControl viene chiamato, tutti gli eventi CurrentItemChanged saranno chiamati per tutti gli altri controlli nella stessa BindingSource. Tuttavia, poiché ControlDoingExplicitUpdate è impostato, non rileggeranno il valore dall'origine dati a meno che non si tratti del controllo che ha effettuato l'aggiornamento. ControlDoingExplicitUpdate è impostato su Nothing dopo che tutti questi eventi sono stati completati, in modo che il normale servizio riprenda.

Spero che tu possa seguire questo, e - di nuovo - chiedo, puoi vedere qualche problema con questo?

risposta

4

Ho avuto requisiti simili per un modulo. Nel mio caso volevo solo che il databinding per tutti i controlli del form si verificasse quando ho fatto clic sul pulsante Salva del modulo.

La soluzione migliore che ho trovato è stata quella di impostare DataSourceUpdateMode di ogni associazione su OnValidation, quindi impostare la proprietà AutoValidate del modulo di contenimento su Disabilita. Ciò impedisce il binding mentre si cambia il focus tra i controlli sul modulo. Quindi, nell'evento Click per il pulsante Salva, convalido manualmente l'input del modulo e, se è OK, richiama il metodo ValidateChildren del modulo per attivare l'associazione.

Questo metodo ha anche il vantaggio di darti il ​​pieno controllo su come convalidare il tuo input. WinForms non include un buon metodo per farlo in modo predefinito.

2

Credo recente ho letto su StackOverflow in cui questo è stato dato come risposta: Disable Two Way Databinding

public static class DataBindingUtils 
{ 
    public static void SuspendTwoWayBinding(BindingManagerBase bindingManager) 
    { 
     if(bindingManager == null) 
     { 
      throw new ArgumentNullException ("bindingManager"); 
     } 

     foreach(Binding b in bindingManager.Bindings) 
     { 
      b.DataSourceUpdateMode = DataSourceUpdateMode.Never; 
     } 
    } 

    public static void UpdateDataBoundObject(BindingManagerBase bindingManager) 
    { 
     if(bindingManager == null) 
     { 
      throw new ArgumentNullException ("bindingManager"); 
     } 

     foreach(Binding b in bindingManager.Bindings) 
     { 
      b.WriteValue(); 
     } 
    } 
} 
Problemi correlati