web-dev-qa-db-fra.com

Lier une étiquette à une "variable"

Supposons que j'ai une variable globale INT nommée X. Comme X est global, nous pouvons supposer que tout ce qui peut en modifier la valeur est modifié à chaque fois.

Disons que j'ai un contrôle Label nommé "label". Voici ce que je veux accomplir: 

Je veux "lier" la valeur de label.Text à la variable X. Ainsi, lorsque la variable X est modifiée, elle est reflétée dans label.Text.

Maintenant, je ne veux pas écrire des écouteurs d'événements et jouer avec des délégués avec celui-ci (je veux le moins de code possible). Existe-t-il un moyen d'utiliser le composant DataBinding pour celui-ci? ou d'autres techniques nouvelles?

Merci, Ian

21
Ian

Si vous souhaitez utiliser l'infrastructure de liaison de données et refléter les modifications apportées à une valeur, vous devez disposer d'un moyen de notifier l'interface utilisateur des modifications apportées à la valeur de liaison.

La meilleure façon de le faire est donc d'utiliser une propriété et d'implémenter l'interface INotifyPropertyChanged, comme ceci:

class frmFoo : Form, INotifyPropertyChanged
{        
    private string _foo;

    public string Foo
    {
        get { return _foo; }
        set
        {
            _foo = value;
            OnPropertyChanged("Foo");
        }
    }

    protected virtual void OnPropertyChanged(string property)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

Rappelez-vous également que vous devez d'abord configurer la liaison sur l'étiquette:

public frmFoo()
{
    InitializeComponent();
    lblTest.DataBindings.Add(new Binding("Text", this, "Foo"));
}
28
Iñaki Elcoro

Pour un programme multi-thread (donc presque tous les programmes Windows Forms), la réponse de iCe n’est pas bonne, car elle ne vous permet pas de changer le libellé de toute façon (vous obtiendrez une erreur de cross-threading). Le moyen le plus simple de résoudre le problème consiste à créer une propriété dans setter: 

private string _labelText;
public string labelText
{
    get { return _labelText; }
    set
    {
        _labelText = value;
        updateLabelText(_labelText); //setting label to value
   }
}

où updateLabelText (string) est thread-safe:

delegate void updateLabelTextDelegate(string newText);
private void updateLabelText(string newText)
{
     if (label1.InvokeRequired)
     {
          // this is worker thread
          updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText);
          label1.Invoke(del, new object[] { newText });
     }
     else
     {
          // this is UI thread
          label1.Text = newText;
     }
}
8
Maciej Oziębły

Je ne pense pas que vous seriez capable de vous lier à une variable publique. Une variable en elle-même n'a pas la capacité d'informer les auditeurs d'un changement de sa valeur.

C'est pourquoi vous devez envelopper la variable dans une propriété. Dans le configurateur, vous déclenchez un événement pour notifier les contrôles d'interface utilisateur qui sont liés à celui-ci, afin qu'ils puissent actualiser et afficher la nouvelle valeur. Le cadre a un mécanisme pour cela - INotifyPropertyChanged - try ce lien pour un tutoriel .

3
Gishu

Créez une propriété pour X. Dans setter, mettez à jour la propriété label.Text.

private int _x;
public int X {
    get 
    { 
        return _x; 
    } 
    set 
    { 
        _x = value;
        label.Text = _x.ToString();
    }
}
0
Krunal