2010-06-30 9 views
17

Скажем, у меня есть глобальная переменная INT с именем X. Поскольку X является глобальным, мы можем предположить, что что-либо может изменить его значение, чтобы оно менялось каждый раз.Привязать ярлык к значению «variable»

Скажите, что у меня есть надпись Label под названием «label». Вот что я хочу сделать:

Я хочу «привязать» значение label.Text к переменной X. Таким образом, когда переменная X будет изменена, она будет отражена обратно на label.Text.

Теперь я не хочу записывать слушателей событий и играть с делегатами с этим (я хочу, чтобы наименьшее количество кода было возможно). Есть ли способ использовать компонент DataBinding для этого? или любые другие новые методы?

Спасибо, Ian

+2

, когда вы имеете в виду глобальную переменную, вы имеете в виду что-то вроде статической переменной/свойство внутри класса? – Gishu

+0

@ Гишу: Да. Подобно public int X – Ian

+0

Обратите внимание, что это называется «переменной экземпляра класса». – Noldorin

ответ

23

Если вы хотите использовать инфраструктуру привязки данных и отражать изменения, внесенные в значение, вам необходимо указать способ уведомления об изменениях, внесенных в значение привязки.

Так что лучший способ сделать это, чтобы использовать свойство и реализовать интерфейс INotifyPropertyChanged, как этот:

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 
} 

Также помните, что вам нужно настроить привязки на этикетке первый:

public frmFoo() 
{ 
    InitializeComponent(); 
    lblTest.DataBindings.Add(new Binding("Text", this, "Foo")); 
} 
+1

Я думаю, что этот ответ - именно то, что мне нужно. Возможно, даже лучше создать копию PropertyChanged перед проверкой на значение null, в противном случае она может измениться до нуля до ее вызова, например: protected virtual void OnPropertyChanged(string property) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(property)); } } (см. Http: // stackoverflow.com/questions/672638/use-of-null-check-in-event-handler/672666 # 672666) –

+0

Я согласен, что это лучшая эталонная реализация шаблона PropertyChanged с поддержкой многопоточных сценариев. –

0

Создать свойство для X. В инкубационном обновления свойство label.Text.

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

Неправильно, если вы делаете это из потока, который не является потоком пользовательского интерфейса, вы вызовете операцию поперечного потока недействительным исключением –

3

Я не думаю, что вы сможете привязываться к общедоступной переменной. Переменная сама по себе не имеет возможности уведомлять слушателей об изменении ее значения.

Вот почему вам нужно обернуть переменную в свойство. В установщике вы поднимаете событие, чтобы уведомить элементы управления пользовательского интерфейса, которые привязаны к нему, чтобы они могли обновлять и отображать новое значение. В структуре есть механизм для этого - INotifyPropertyChanged - попробуйте this link for a how-to.

7

Для многопоточной программы (так почти каждая программа для окон) ответ iCe не очень хороший, потому что он не позволит вам менять метку в любом случае (вы получите некоторую ошибку перекрестного потока). Самый простой способ решить эту проблему создает свойство в инкубаторе:

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

где updateLabelText (строка) потокобезопасен:

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; 
    } 
} 
+0

спасибо! это, на мой взгляд, самое простое и лучшее решение. – user2979010

Смежные вопросы