Как получить события от вспомогательных элементов управления пользовательского элемента управления в приложении WinForms?

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

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

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

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

По сути, я хочу, чтобы данные обновлялись, когда пользователь переключает субэлементы управления ИЛИ покидает пользовательский элемент управления, но не проверяет. Когда пользователь покидает элемент управления, я хочу обновить И проверить. Прямо сейчас выход из пользовательского элемента управления приводит к двойному срабатыванию проверки.


person Brock Greman    schedule 02.10.2008    source источник
comment
Что не так с привязкой главной формы к различным событиям элементов управления? Существует множество событий, которые срабатывают для большинства элементов управления winform.   -  person Sekhat    schedule 02.10.2008
comment
Я думаю, я просто не понимаю, чего ты хочешь достичь: P   -  person Sekhat    schedule 02.10.2008
comment
Чтобы ответить на первый вопрос, через дизайнер (который я, относительно новичок в C #, использовал для редактирования моего графического интерфейса), моя форма имеет доступ только к событиям, инициированным пользовательским элементом управления, а не его подэлементы управления. Чего я не помнил, так это того, что я могу запускать свои собственные события и обрабатывать их.   -  person Brock Greman    schedule 02.10.2008


Ответы (5)


Лучшей практикой было бы выставлять события на UserControl, которые поднимают события до родительской формы. Я пошел вперед и собрал пример для вас. Вот описание того, что дает этот пример.

  • UserControl1
  • Создайте UserControl с TextBox1
  • Зарегистрируйте публичное мероприятие на UserControl под названием ControlChanged
  • В UserControl зарегистрируйте обработчик события TextBox1 TextChangedEvent.
  • В функции обработчика TextChangeEvent я вызываю событие ControlChanged, чтобы всплывать в родительской форме.
  • Form1
  • Перетащите экземпляр UserControl1 в дизайнер
  • Зарегистрируйте обработчик событий на UserControl1 для MouseLeave и для ControlChanged

Вот снимок экрана, показывающий, что событие ControlChanged, которое я определил для UserControl, доступно через UX в Visual Studio в родительской форме Windows.

Обработчики событий для управления пользователями

person Eric Schoonover    schedule 02.10.2008
comment
Спасибо, это то, что я закончил делать, за исключением того, что вместо MouseLeave я использовал FocusLeave, поскольку потенциальная ошибка каждый раз, когда пользователь перемещает свою мышь, может раздражать. Также спасибо за то, что проделали всю работу для этого! - person Brock Greman; 02.10.2008
comment
поэтому, если у вас есть много разных элементов управления (скажем, текстовое поле, кнопка, флажок и метка), и что все соответствующие/фактические события этих элементов управления обрабатываются внутри пользовательского элемента управления (автономный пользовательский элемент управления) и вы хотели добавить одно событие (скажем, MyControl.OnClick) в форму контейнера, могли бы вы перехватить все события подуправления с помощью одного метода/механизма, чтобы всплыть одно событие Click, или вам все равно придется вручную подключаться каждое событие подуправления и обрабатывать всплытие самостоятельно для каждого из них? - person MaxOvrdrv; 22.05.2015
comment
Ссылка не работает. Код должен идти в виде текста в ответе, а не в виде ссылки для загрузки zip-файла. - person ardila; 23.03.2016
comment
К сожалению, @spoon16 не посещал Stack Overflow уже полгода, так что вместе с ним код может никогда не вернуться... - person Breeze; 05.04.2016

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

Ваш сценарий довольно сложный, но не неслыханный. (На самом деле я нахожусь в очень похожем режиме в одном из моих текущих проектов.) Я подхожу к этому так, что пользовательский элемент управления отвечает за свою собственную проверку. Я не использую CausesValidation; вместо этого в соответствующей контрольной точке пользователя я выполняю проверку с помощью переопределения ValidateChildren(). (Обычно это происходит, когда пользователь нажимает «Сохранить» или «Далее» в пользовательском элементе управления, для меня.)

Если вы не знакомы с вашим пользовательским интерфейсом управления, это может быть не на 100% правильным подходом для вас. Однако, если вы вызываете пользовательские события (возможно, с пользовательским EventArgs, который указывает, выполнять ли проверку или нет), вы сможете достичь того, чего хотите.

person John Rudy    schedule 02.10.2008

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

// CustomControl.cs
// Assumes a Button 'myButton' has been added through the designer

// we need a delegate definition to type our event
public delegate void ButtonClickHandler(object sender, EventArgs e);

// declare the public event that other classes can subscribe to
public event ButtonClickHandler ButtonClickEvent;

// wire up the internal button click event to trigger our custom event
this.myButton.Click += new System.EventHandler(this.myButton_Click);
public void myButton_Click(object sender, EventArgs e)
{
  if (ButtonClickEvent != null)
  {
    ButtonClickEvent(sender, e);
  }
}

Затем в форме, которая использует этот элемент управления, вы подключаете событие, как и любое другое:

// CustomForm.cs
// Assumes a CustomControl 'myCustomControl' has been added through the desinger
this.myCustomControl.ButtonClickEvent += new System.EventHandler(this.myCustomControl_ButtonClickEvent);
myCustomControl_ButtonClickEvent(object sender, EventArgs e)
{
  // do something with the newly bubbled event
}
person Goyuix    schedule 29.03.2010
comment
Может быть, я ошибаюсь или я не очень понимаю идею, но разве не должно быть new MyProject.CustomControl.ButtonClickHandler() вместо new System.EventHandler() в CustomForm.cs? - person MRM; 19.02.2013

Если кто-то все еще задается вопросом, как имитировать всплывающую подсказку событий в WinForm, метод Application.AddMessageFilter — хорошее место для просмотра.

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

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

person Ori Calvo    schedule 04.02.2015

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

Если вы можете реорганизовать/реструктурировать свой дизайн таким образом, чтобы элементы управления работали с общей моделью данных (очевидным выбором являются MVC/MVP), то вы можете просто применить к модели общие шаблоны WinForms, такие как события PropertyChanged, чтобы сообщить вашей основной форме и любым другим элементам управления. которые используют эти данные для обновления себя.

Короче говоря, другие ответы разумны в том смысле, что они отвечают на заданный вопрос. Но с точки зрения качества кода, я думаю, лучший ответ — отделить ваши данные от пользовательского интерфейса.

person hemp    schedule 29.03.2010