2016-05-17 10 views
1

Предположим, у меня есть простая форма в C# (winforms) с двумя текстовыми полями, одним слайдером и объектом, называемым «the_volume». Событие (OnPropertyChanged) отправляется всякий раз, когда изменяется значение «the_volume.value». Как можно CLEANLY синхронизировать четыре объекта, не вызывая бесконечного цикла?Бесконечный цикл событий

  • Не отсоединяя слушателей событий
  • без использования логическое значение "караул"
  • Без использования Databinding

небольшой пример: изменения слайдера -> форма :: slider_changed -> the_volume установлен -> форма :: the_volume_changed -> задает значения ползунка и тексбокса -> бесконечный цикл ...

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

1- Как я могу узнать, будут ли элементы управления .net делать то же самое? (Т.е. не вызывает, если значение равно)

2- Какие ошибки мне, что было бы «бесполезным» сеттер вызов с этим решением (набор -> изменен -> набор -> остановка петли)

+2

afaik 'TextBox' и' Slider' не создают события изменения, если не было изменения _real_ (если значение _new_ совпадает с _old_ одним). Поэтому не должно быть бесконечного цикла. –

+0

, но лишний вызов «сеттера» можно избежать? – d08z

+0

не думайте, что это проблема с производительностью, поэтому не нужно ее избегать. Если вы действительно хотите этого избежать, я бы предложил «guard» boolean. –

ответ

0

Я знаю, что это вопрос WinForms, но способ, которым WPF это делает, должен помочь вам. Вы можете исследовать INotifyPropertyChanged примеры более подробно, но вот основы:

//have a backing variable 
private double _volume = 0; 

//have a property 
public double Volume 
{ 
    get { return _volume; } 
    set 
    { 
     // prevent any event firing if nothing changed 
     if(_volume == value) 
     { 
      return; 
     } 

     // now we can set 
     _volume = value; 

     // something really changed, fire some event 
     this.NotifyPropertyChanged(); 
    } 
} 

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

+0

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

+0

Это проверка, и ничего не устанавливается, если только это не нужно. Во многих ваших комментариях вы упоминали «дополнительный звонок сеттера». Может быть, я не понимаю, что вы подразумеваете под этим. Над головой событий обжига дороже, чем при проверке или установке значения. Помните, что память уже выделена для хранения вашей переменной, поэтому установка значения будет примерно такой же минимальной, как вы могли бы. Вещь, которую вы хотите избежать, - это перерисовка пользовательского интерфейса, поэтому предотвращение события будет вашим лучшим выбором, если производительность является проблемой. – ManOVision

+0

Textbox1 setter -> измененное событие -> Textbox2 setter -> changed -> Textbox1 setter -> --end of loop-- Но вы правы, это действительно ничего не работает – d08z

0

У меня был бы единственный объект, который отвечает за маршрутизацию событий. Назовем это VolumeChangedEventRouter. У этого было бы собственное событие «с измененной громкостью», к которому могли бы подписаться другие сущности.

VolumeChangedEventRouter будет подписаться на (или подписаться) на каждый из ваших элементов управления, который может поднять событие «с измененной громкостью».

Затем каждое ваше управление будет подписано (или будет подписано) на событие «с измененной громкостью» VolumeChangedEventRouter.

Тогда VolumeChangedEventRouter знал бы текущий том, и, следовательно, он знал бы, изменился ли он и, следовательно, передать ли это событие своим подписчикам.

Вы, вероятно, используете инъекцию зависимости, чтобы передать VolumeChangedEventRouter каждому из классов, которые должны подписаться на событие с измененной громкостью. (Возможно, вы даже хотите, чтобы дизайн VolumeChangedEventRouter так, что он реализует интерфейс, который содержит только «объем изменился» событие, и передать к элементам управления, чтобы свести к минимуму зависимости.)

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

+0

Как элемент управления TextBox может подписать событие? – d08z

+0

@ d08z Вам нужен контроллер для TextBox - обычно либо пользовательский элемент управления, который содержит его (для простых случаев), либо отдельный класс контроллера (для более сложных случаев). Контроллер будет подписаться на событие и обработать его соответствующим образом. –

+0

Да, но все равно будут дополнительные бесполезные звонки сеттера. Однако я не думаю, что это важно для производительности. – d08z