Как получить события из субэлементов управления пользователя в приложении WinForms? - PullRequest
11 голосов
/ 02 октября 2008

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

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

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

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

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

Ответы [ 5 ]

15 голосов
/ 02 октября 2008

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

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

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

Обработчики событий для контроля пользователя http://friendfeed.s3.amazonaws.com/0d5a3968cb785625c8afb3974a8d84894c476291

2 голосов
/ 29 марта 2010

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

// 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
}
2 голосов
/ 02 октября 2008

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

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

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

1 голос
/ 04 февраля 2015

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

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

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

0 голосов
/ 29 марта 2010

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

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

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

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