Question

J'ai dans ma base de données un champ binaire difficile à décrire dans une interface utilisateur à l'aide d'une case à cocher du type "Is XXXX?". Je préférerais utiliser une paire de boutons radio (par exemple, "Faites-le à la manière de Foo" et "Faites-le à la barre"), mais tous les autres champs de mon formulaire sont liés à un objet de gestion. J'aimerais également lier la paire de boutons radio à l'objet métier, mais je n'ai pas encore trouvé le moyen de le faire. Je peux lier l'un des boutons au champ, de sorte que le champ soit défini sur "true". si le bouton est sélectionné, mais que l'autre bouton désélectionne le premier (c'est-à-dire que les deux boutons radio sont correctement appariés), la valeur du champ n'est pas mise à jour pour refléter cela.

J'aimerais pouvoir dire

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

mais je suis à peu près sûr que ça jettera quand ça va. Existe-t-il un moyen plus simple ou devrais-je simplement réfléchir davantage à la formulation d'une seule case à cocher? Je ne veux pas ajouter de fonctions supplémentaires pour gérer quelque chose d'aussi trivial ...

ETA: Un intervenant a suggéré d’envisager un menu déroulant (ComboBox). J'y avais pensé, mais comment pourrais-je lier cela à un champ booléen dans une base de données / Propriété dans un objet métier? Si je lie l'élément SelectedItem à la propriété useFoo, que va-t-il dans la collection Items? Aurais-je juste à ajouter " True " et "False", ou pourrais-je en quelque sorte ajouter un objet paire paire clé / valeur qui lie un élément affiché ("Utiliser Foo" / "Ne pas utiliser Foo") à la valeur booléenne qui le sous-tend? J'ai du mal à trouver des documents à ce sujet.

À propos de la réponse: la solution que j’ai finalement trouvée impliquait la modification de l’objet métier - l’idée de base est très similaire à celle publiée par Gurge, mais je l’ai trouvée séparément avant de lire sa réponse. En bref, j'ai ajouté une propriété distincte qui renvoie simplement ! UseFoo . Un bouton radio est lié à source.UseFoo , l'autre est lié à source.UseBar (nom de la nouvelle propriété). Il est important de vous assurer que la nouvelle propriété a à la fois des accesseurs et des passeurs, sinon vous vous retrouverez avec un comportement vraiment étrange.

Était-ce utile?

La solution

J'ai trouvé un moyen de le faire en utilisant DataSet / DataTable.

Je crée une colonne calculée dans le DataTable avec l'expression IIF (Foo = true, false, true) . Appelons cette colonne Bar .

La barre est de type booléen. Vous pouvez maintenant lier un RadioButton.Checked à Foo et un à Bar .

Pour que Bar cocher / décocher soit renvoyé à Foo , vous devez accéder au code DataTable généré et ajouter une ligne, la dernière de cet exemple:

[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;
    }
}

Autres conseils

  1. Liez le RadioButton directement lié à votre valeur booléenne (c’est-à-dire qu’il est coché lorsque la valeur est true ).
  2. Ajoutez un gestionnaire d'événements à l'événement CheckedChanged sur ce RadioButton qui se présente comme suit:

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

Si votre objet métier implémente INotifyPropertyChanged (ce qui facilite la liaison), vous pouvez ajouter le code suivant à l'interface visuelle où BO est votre objet métier et est déclaré avec les événements et BO. La valeur est la propriété booléenne que vous souhaitez associer.

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

Les liaisons suivantes relieront les boutons radio.

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

L’interface visuelle doit également implémenter INotifyPropertyChanged. Cette méthode fonctionne dans les deux sens: la valeur d'origine est mise à jour si l'interface change et si la valeur d'origine change, l'interface se mettra à jour correctement.

J'ai rencontré le même problème et découvert qu'il était en fait possible avec la liaison de données 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

Par défaut, DataSourceUpdateMode est défini sur OnValidation . En le définissant sur OnPropertyChanged , la modification est immédiatement transmise à l'objet databound.

Mon objet métier implémente INotifyPropertyChanged ;

En testant cette solution, j'ai découvert que mon événement OnPropertyChanged avait été déclenché deux fois lorsque je cliquais sur button2 . Pour éviter cela, définissez simplement

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

comme indiqué ici: TextBox laisse les causes que PropertyChanged soit renvoyé deux fois

Faites-le manuellement dans le code. Lorsque vous chargez le formulaire, définissez vos boutons radio en fonction de votre base de données. Lorsque vous appuyez sur un bouton "Enregistrer" bouton magasin de l'état que vous le souhaitez. Cet exemple stocke les radios en tant que champs de bits dans la base de données.

        // 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;

J'ai essayé de faire glisser des éléments de la "Sources de données". dans Visual Studio 2015 lorsque j'ai défini mes boutons radio comme étant des booléens dans le tableau, mais que des problèmes se posent, les booléens n'étant pas mis à jour avec la valeur false lorsqu'un autre bouton radio est sélectionné. Lors de la modification de l'option "causesValidation" fausses cases radio désactivées automatiquement lorsque vous passez d'un autre champ de saisie de texte à un autre.

Vous ne devriez avoir à relier qu’un des contrôles tant que vous vous assurez qu’ils appartiennent au même groupe.

Vous pouvez également envisager un DropDown.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top