WinForms INotifyPropertyChanged.NET обновляет всю привязку, когда каждый изменяется. Лучший путь?

В окна формируют приложение, изменение свойства, которое инициировало INotifyPropertyChanged, приведет к форме, читая КАЖДОЕ свойство из моего связанного объекта, не только измененное свойство. (См. пример кода ниже),

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

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

Я пропускаю что-то? Существует ли лучший путь? Не говорите для использования другой технологии презентации - я делаю это на Windows Mobile (хотя поведение происходит на полной платформе также).

Вот некоторый игрушечный код для демонстрации проблемы. Нажатие кнопки приведет к ОБОИМ текстовым полям, заполняемым даже при том, что одно свойство изменилось.

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace Example
{
public class ExView : Form
{
    private Presenter _presenter = new Presenter();
    public ExView()
    {
        this.MinimizeBox = false;

        TextBox txt1 = new TextBox();
        txt1.Parent = this;
        txt1.Location = new Point(1, 1);
        txt1.Width = this.ClientSize.Width - 10;
        txt1.DataBindings.Add("Text", _presenter, "SomeText1");

        TextBox txt2 = new TextBox();
        txt2.Parent = this;
        txt2.Location = new Point(1, 40);
        txt2.Width = this.ClientSize.Width - 10;
        txt2.DataBindings.Add("Text", _presenter, "SomeText2");

        Button but = new Button();
        but.Parent = this;
        but.Location = new Point(1, 80);
        but.Click +=new EventHandler(but_Click);
    }

    void but_Click(object sender, EventArgs e)
    {
        _presenter.SomeText1 = "some text 1";
    }
}

public class Presenter : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    private string _SomeText1 = string.Empty;
    public string SomeText1
    {
        get
        {
            return _SomeText1;
        }
        set
        {
            _SomeText1 = value;
            _SomeText2 = value; // <-- To demonstrate that both properties are read
            OnPropertyChanged("SomeText1");
        }
    }

    private string _SomeText2 = string.Empty;
    public string SomeText2
    {
        get
        {
            return _SomeText2;
        }
        set
        {
            _SomeText2 = value;
            OnPropertyChanged("SomeText2");
        }
    }

    private void OnPropertyChanged(string PropertyName)
    {
        PropertyChangedEventHandler temp = PropertyChanged;
        if (temp != null)
        {
            temp(this, new PropertyChangedEventArgs(PropertyName));
        }
    }
}

}

24
задан Nate 12 May 2010 в 15:50
поделиться

1 ответ

Причина, по которой все свойства считываются при срабатывании события, кроется в методе PushData, вызываемом для объекта привязки при срабатывании события ProperyChanged. Если вы посмотрите на трассировку стека, вы заметите, что вызывается метод PropValueChanged внутреннего объекта BindToObject, который, в свою очередь, вызывает событие Oncurrentchanged в BindingManager. Механизм привязки отслеживает текущие изменения элемента, но не делает более детального различия. "Виновный" метод PushData вызывает геттер ваших свойств (взгляните на код с помощью отражателя). Так что выхода нет. При этом, как показывает практика, в методах доступа get и set не рекомендуется выполнять тяжелую обработку, используйте для этого отдельные методы get и set (если возможно)

. Также прочтите эту статью, и это комментарий, в частности ( http://www.codeproject.com/Messages/2514032/How-Binding-watches-control-properties-ie-how-doe.aspx ), который точно объясняет, как событие propertychanged запускается, хотя это не решит вашу проблему с геттером: http://www.codeproject.com/KB/database/databinding_tutorial.aspx?msg=2514032

Идея для изучения состоит в том, чтобы задержать вызов геттера . Вы можете добиться этого, поиграв со свойством ControlUpdateMode привязки. Если для этого значения установлено значение «Никогда», соответствующий элемент управления не будет обновляться при изменении. Однако, когда вы переключаете значение обратно на OnPropertyChanged, будет вызван метод PushData, поэтому получат доступ к геттерам. Итак, учитывая ваш пример, этот код временно предотвратит обновление текстового поля 2:

void but_Click(object sender, EventArgs e)
        {                   
            txt2.DataBindings[0].ControlUpdateMode = ControlUpdateMode.Never;
            _presenter.SomeText1 = "some text 1";
        }
15
ответ дан 29 November 2019 в 00:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: