Двусторонняя привязка в приложении Winforms делает ввод текста в TextBox болезненно медленным

Я установил двухстороннюю привязку между моей формой (у нее 32 элемента управления) и экземпляром моего класса, но каждый символ, введенный в TextBox, имеет задержку в 1/2 секунды, что делает приложение практически непригодным для использования.
Когда Я использую DataSourceUpdateMode.Never, проблема не возникает, что ясно указывает на то, что виновата двусторонняя привязка.

Обратите внимание, что если я устанавливаю DataSourceUpdateMode.Never для каждого элемента управления, кроме одного, задержка существует для этого одного элемента управления, поэтому проблема не связана с количеством связанных элементов управления.

parameterTagRecord = new PETParameterTagRecord(TagID);
baseTagNameTB.DataBindings.Add("Text", parameterTagRecord, 
         "BaseTagName", true, DataSourceUpdateMode.OnPropertyChanged);

И выдержка из моего класса:

public class PETParameterTagRecord : PETBaseObject, INotifyPropertyChanged
{
        private string _baseTagName = Constants.NullString;
        public event PropertyChangedEventHandler PropertyChanged;

        public string BaseTagName
        {
            get { return _baseTagName; }
            set
            {
                _baseTagName = value;
                NotifyPropertyChanged("BaseTagName");
            }
        }

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

Что я делаю не так?


person BlazingFrog    schedule 13.02.2012    source источник
comment
Удалось ли вам просмотреть ответ на этот вопрос? Объясните/помогите?   -  person Andy    schedule 18.07.2013


Ответы (2)


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

Итак, сначала попробуйте изменить привязку следующим образом:

baseTagNameTB.DataBindings.Add("Text", parameterTagRecord,  
         "BaseTagName", true, DataSourceUpdateMode.OnValidation);

См. эту ссылку MSDN: http://msdn.microsoft.com/en-us/library/system.windows.forms.datasourceupdatemode.aspx. Это означает, что вместо того, чтобы каждое нажатие клавиши приводило к тому, что новое строковое значение вставлялось в свойство, оно будет делать это только при проверке (что происходит как часть элемента управления, теряющего фокус).

Во-вторых, измените реализацию свойства, чтобы она соответствовала этому:

public string BaseTagName   
{   
    get { return _baseTagName; }   
    set   
    {   
        if (_baseTagName != value) {
          _baseTagName = value;   
          NotifyPropertyChanged("BaseTagName");   
        }
    }   
}

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

person Andy    schedule 13.02.2012
comment
Привет, Энди, я не уверен, откуда появляется изображение из-за этого нажатия клавиши или потери фокуса. Я предполагаю, что привязка данных не заботится об этом. Можете ли вы объяснить немного больше? - person Digvijay; 13.02.2012
comment
Спасибо, Энди, это то, что я никогда не исследовал для обычных сценариев привязки, которые до сих пор отлично работали для меня. Я посмотрел на перечисление DataSourceIpdateMode, но до сих пор не понимаю. Вы имеете в виду, что RaisePropertyChanged будет поднят на LostFocus или KeyPress? - person Digvijay; 13.02.2012
comment
У меня была такая же проблема, помогло изменение режима обновления с OnPropertyChanged на OnValidation: DataSourceUpdateMode.OnPropertyChanged => DataSourceUpdateMode.OnValidation - person Santhos; 11.07.2012

Я столкнулся с той же самой проблемой с BindingSource. Это не имеет ничего общего с режимом обновления или слишком частыми уведомлениями (хотя и косвенно). Текущая реализация приводит к обновлению каждого связанного элемента при изменении любого свойства. Таким образом, причина, по которой OnValidation менее проблематична, очевидна, это происходит реже.

Проверить тоже довольно легко. Добавьте два счетчика, увеличивая каждый при обращении к геттеру или при вызове NotifyProperChanged. В моем случае, примерно с 40 элементами, я был бы на 1/40 после загрузки формы. Добавить символ в текстовое поле, вдруг в 2/80. Удерживая клавишу нажатой, мое приложение перестало отвечать. Как только он, наконец, догнал, счет стал чем-то нелепым, например, 50/2000. Все из-за изменения одного единственного элемента.

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

person knrdk    schedule 10.06.2013
comment
На самом деле это желаемое поведение; представьте, что у вас есть текстовые поля количества и цены, а также общее текстовое поле, которое показывает общее количество (количество * цена). Я, конечно, ожидаю увидеть полное обновление, и текущая реализация делает именно это. Проблема заключается в режиме обновления, поскольку OnPropertyChanged вызовет событие ДЛЯ КАЖДОГО НАЖАТИЯ КЛАВИШИ, которое делает пользователь; OnValidated отправляет событие только после того, как элемент управления теряет фокус. - person Andy; 18.07.2013