Почему связывание срабатывает, даже если связанное свойство не изменяется? - PullRequest
2 голосов
/ 07 апреля 2009

С кодом ниже я получаю и сообщение Firing C Binding, и сообщение Firing F Binding. Это почему? Я ожидаю получить только сообщение Firing C Binding.

class Program : Form
{
    private Label lblC;
    private Label lblF;
    private Button btnCUp;
    private Temp t;

    public Program()
    {
        lblC = new Label();
        lblF = new Label();
        btnCUp = new Button();
        t = new Temp();

        lblC.Location = new Point(22, 21);
        lblC.Size = new Size(35, 13);
        Binding b = new Binding("Text", t, "C");
        b.Format += new ConvertEventHandler(CLabelFormat);
        lblC.DataBindings.Add(b);

        lblF.Location = new Point(108, 21);
        lblF.Size = new Size(35, 13);
        Binding b2 = new Binding("Text", t, "F");
        b2.Format += new ConvertEventHandler(FLabelFormat);
        lblF.DataBindings.Add(b2);

        btnCUp.Location = new Point(45, 55);
        btnCUp.Text = "C Up";
        btnCUp.Click += new EventHandler(btnCUp_Click);

        this.ClientSize = new Size(165, 113);
        this.Controls.Add(lblC);
        this.Controls.Add(lblF);
        this.Controls.Add(btnCUp);
    }

    private void CLabelFormat(object sender, ConvertEventArgs cevent)
    {
        MessageBox.Show("Firing C Binding");
    }

    private void FLabelFormat(object sender, ConvertEventArgs cevent)
    {
        MessageBox.Show("Firing F Binding");
    }

    [STAThread]
    public static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Program());
    }

    private void btnCUp_Click(object sender, EventArgs e)
    {
        t.incC();
    }
}

class Temp : INotifyPropertyChanged
{
    private double tempC;
    private double tempF;

    public event PropertyChangedEventHandler PropertyChanged;

    public Temp()
    {
        tempC = 0;
        tempF = ctof(tempC);
    }

    private void NotifyPropertyChanged(String field)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(field));
        }
    }

    private double ctof(double c)
    {
        return c * 9.0 / 5.0 + 32;
    }

    public void incC()
    {
        ++tempC;
        tempF = ctof(tempC);
        NotifyPropertyChanged("C");
        //NotifyPropertyChanged("F");
    }

    public double C
    {
        get { return tempC; }
    }

    public double F
    {
        get { return tempF; }
    }
}

Если я удаляю комментарий перед NotifyPropertyChanged("F"), то при нажатии кнопки я получаю четыре окна сообщения. Два для "Firing C Binding" и два для "Firing F Binding".

Как я могу изменить код, чтобы получить только один из них?


РЕДАКТИРОВАТЬ: Я пытался посмотреть на источник Binding (используя Reflector), чтобы увидеть, что он делает, когда происходит событие PropertyChanged, но ничего не смог найти. Кто-нибудь может дать некоторое представление? Я хочу подтвердить, что ему важно, какое поле изменилось.

РЕДАКТИРОВАТЬ: Заменил мой код полностью компилируемым примером реализации, который демонстрирует проблему.

Ответы [ 2 ]

2 голосов
/ 27 июня 2013

Событие PropertyChanged запускается только один раз, что вы можете проверить сами:

t.PropertyChanged += t_PropertyChanged;

void t_PropertyChanged(object sender, PropertyChangedEventArgs e) {
  MessageBox.Show("Property Changed: " + e.PropertyName);
}

Событие Binding Format - это нечто другое:

Событие Format наступает всякий раз, когда изменяется текущее значение BindingManagerBase, которое включает:

  • Первый раз, когда свойство связано.
  • Каждый раз, когда Позиция меняется.
  • Всякий раз, когда связанный с данными список сортируется или фильтруется, что достигается, когда DataView предоставляет список.

Таким образом, может показаться, что событие Format срабатывает при изменении свойства в текущем значении.

0 голосов
/ 07 апреля 2009

Я бы предположил, что при изменении одного свойства это указывает на то, что оно могло повлиять на другое свойство, в результате чего это свойство также запускает обновление. Довольно часто события изменения свойств запускаются для объекта, даже если он не изменился, потому что разработчик не хочет фактически проверять изменение, и поэтому просто запускает событие в сценариях, где оно могло измениться. Мой внутренний инстинкт подсказывает, что это может быть то, что вы испытываете.

Однако может также случиться так, что независимо от того, что прослушивает событие PropertyChanged, на самом деле не проверяется имя измененного свойства. Это также может вызвать ту же проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...