Domanda

Ho un campo binario nel mio database che è difficile da descrivere in una UI usando una singola casella di controllo "È XXXX". Preferirei usare un paio di pulsanti di opzione (ad es. "Fai in modo Foo" e "Fai in modo Bar"), ma in questo momento tutti gli altri campi del mio modulo sono associati a un oggetto business. Vorrei collegare anche la coppia di pulsanti di opzione all'oggetto business, ma non ho ancora trovato un buon modo per farlo. Posso associare uno dei pulsanti al campo, in modo tale che il campo sia impostato "vero" se il pulsante è selezionato, ma mentre si seleziona l'altro pulsante deseleziona il primo (ovvero, i due pulsanti di opzione sono correttamente accoppiati), il valore del campo non si aggiorna per riflettere questo.

Mi piacerebbe poterlo dire

button1.DataBindings.Add(new Binding("checked", source, "useFoo"));
button2.DataBindings.Add(new Binding("checked", source, "!useFoo"));

ma sono abbastanza sicuro che lancerà quando corre. C'è un modo più semplice o dovrei solo riflettere di più su come esprimere una singola casella? Non voglio aggiungere funzioni extra per gestire qualcosa di così banale ...

ETA: un commentatore ha suggerito di considerare un menu a discesa (ComboBox). Ci avevo pensato, ma come avrei potuto legarlo ai dati in un campo booleano in un database / Proprietà in un oggetto business? Se associo SelectedItem alla proprietà useFoo, cosa andrebbe nella raccolta Articoli? Dovrei aggiungere solo " True " e "Falso", o potrei in qualche modo aggiungere un oggetto coppia chiave / valore che lega un oggetto visualizzato ("quotare Usa Foo" / "non usare Foo") al valore booleano dietro di esso? Ho difficoltà a trovare documenti su questo.


Informazioni sulla risposta: la soluzione che ho escogitato ha comportato la modifica dell'oggetto business: l'idea di base è molto simile a quella pubblicata da Gurge, ma l'ho trovata separatamente prima di leggere la sua risposta. In breve, ho aggiunto una proprietà separata che restituisce semplicemente ! UseFoo . Un pulsante di opzione è associato a source.UseFoo e l'altro è associato a source.UseBar (il nome della nuova proprietà). È importante assicurarsi che la nuova proprietà abbia sia getter che setter, altrimenti finirai con un comportamento davvero strano.

È stato utile?

Soluzione

Ho trovato un modo per farlo usando DataSet / DataTable.

Faccio una colonna calcolata nella DataTable con l'espressione IIF (Foo = true, false, true) . Chiamiamo quella colonna Bar .

Bar è di tipo Booleano. Ora puoi associare un RadioButton.Checked a Foo e uno a Bar .

Per ottenere Bar selezionando / deselezionando per propagare indietro a Foo devi andare al codice DataTable generato e aggiungere una riga, l'ultima in questo esempio:

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public bool Bar {
    get {
        try {
            return ((bool)(this[this.tableradio.BarColumn]));
        }
        catch (global::System.InvalidCastException e) {
            throw new global::System.Data.StrongTypingException("The value for column \'Bar\' in table \'radio\' is DBNull.", e);
        }
    }
    set {
        this[this.tableradio.BarColumn] = value;
        this[this.tableradio.FooColumn] = !value;
    }
}

Altri suggerimenti

  1. Associa il RadioButton che è direttamente collegato al tuo valore booleano (cioè viene verificato quando il valore è true ).
  2. Aggiungi un gestore eventi all'evento CheckedChanged su questo RadioButton simile al seguente:

    private void radioButton_CheckedChanged(object sender, EventArgs e)
    {
        foreach (Binding b in ((Control)sender).DataBindings)
            b.WriteValue();
    }
    

Se il tuo oggetto di business implementa INotifyPropertyChanged (che rende il lavoro di rilegatura più gradevole), puoi aggiungere il seguente codice all'interfaccia visiva in cui BO è il tuo oggetto di business e viene dichiarato con gli eventi e BO. Valore è la proprietà booleana a cui desideri associare.

Public Property NotValue() As Boolean
    Get
        Return Not BO.Value
    End Get
    Set(ByVal value As Boolean)
        BO.Value = Not value
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NotValue"))
    End Set
End Property


Private Sub BO_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Handles BO.PropertyChanged
    If e.PropertyName = "Value" Then
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NotValue"))
    End If
End Sub

I seguenti collegamenti agganceranno i pulsanti di opzione.

RBTrue.DataBindings.Add(New Binding("Checked", Me.BO, "Value", False, DataSourceUpdateMode.OnPropertyChanged))
RBFalse.DataBindings.Add(New Binding("Checked", Me, "NotValue", False, DataSourceUpdateMode.OnPropertyChanged))

L'interfaccia visiva dovrebbe anche implementare INotifyPropertyChanged. Questo metodo funziona in entrambi i modi: il valore originale viene aggiornato se l'interfaccia cambia e se il valore originale cambia l'interfaccia verrà aggiornata correttamente.

Ho riscontrato lo stesso problema e ho scoperto che in realtà è possibile con il databinding standard:

button1.DataBindings.Add(new Binding("checked", source, "useFoo", false, DataSourceUpdateMode.OnPropertyChanged);
// no need to databind button 2, since button1.checked 
// is set to false when button2 is checked

Per impostazione predefinita, DataSourceUpdateMode è impostato su OnValidation . Impostandolo su OnPropertyChanged , la modifica viene propagata immediatamente all'oggetto database.

Il mio oggetto business implementa INotifyPropertyChanged ;

Testando questa soluzione, ho scoperto che il mio evento OnPropertyChanged è stato generato due volte mentre facevo clic su button2 . Per evitarlo, imposta semplicemente

button1.CausesValidation = false;
button2.CausesValidation = false;

come mostrato qui: Congedo TextBox provoca il licenziamento di PropertyChanged due volte

Fallo manualmente nel codice. Quando si carica il modulo, impostare i pulsanti di opzione in base al database. Quando premi un pulsante " salva " pulsante store de state come desideri. Questo esempio memorizza le radio come campi di bit nel database.

        // Load radio state
        radioButton1.Checked = ((myModel)myBindingSource.DataSource).boolOption1;
        radioButton2.Checked = ((myModel)myBindingSource.DataSource).boolOption2;

-

        // Save radio state
        ((myModel)myBindingSource.DataSource).boolOption1 = radioButton1.Checked;
        ((myModel)myBindingSource.DataSource).boolOption2 = radioButton2.Checked;

Ho provato a trascinare gli elementi da " Origini dati " pannello in Visual Studio 2015 quando ho definito i miei pulsanti di opzione come valori booleani nella tabella, ma si verificano problemi con i valori booleani che non vengono aggiornati su false quando viene selezionato un altro pulsante di opzione. Quando si modifica " causeValidation " ai falsi pulsanti radio deselezionati automaticamente quando si salta tra altri campi di input di testo.

Dovresti solo associare uno dei controlli purché tu ti assicuri che siano nello stesso gruppo.

Potresti anche considerare un DropDown.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top