На самом деле событие PreNotifyInput срабатывает при событии MouseLeftButtonUp, но затем PostNotifyInput срабатывает до фактической вставки.
Вот последовательность операций:
- Пользователь отпускает кнопку мыши в пункте меню
- Ваш обработчик события PreNotifyInput называется
- Возникает событие MouseLeftButtonUp, которое всплывает до MenuItem
- MenuItem обрабатывает MouseButtonUp и преобразует его в OnClick
- OnClick вызывает PreviewClickEvent, затем планирует диспетчерский обратный вызов для вызова события Click и выполнения команды
Ваш обработчик события PostNotifyInput называется , так как событие MouseLeftButtonUp обрабатывается
Любой рендеринг, запланированный Диспетчером, завершается
Диспетчер вызывает обратный вызов в MenuItem
- MenuItem запускает событие Click, которое ничего не делает
- MenuItem выполняет команду Вставить
- TextBox обрабатывает команду Вставить и вставляет данные
- TextBox запускает событие TextChanged
В WPF эффекты «пользовательского ввода» могут произвольно задерживаться обратными вызовами диспетчера и т. Д., Поэтому вы не можете знать, вызвано ли изменение пользовательским вводом или нет.
На самом деле, теоретически это вообще верно. Рассмотрим следующие сценарии:
- Пользователь нажимает кнопку в другом месте вашего приложения, которая вызывает загрузку новых данных, которые обновляют ваше значение.
- Пользователь нажимает кнопку в другом приложении , которое записывает файл, заставляя ваше приложение обновлять и отображать новые данные.
- Пользователь заходит на другой компьютер и обновляет некоторые данные на веб-сайте. Ваше приложение отслеживает этот веб-сайт и обнаруживает изменение.
Очевидно, что в каждом из этих случаев изменение было вызвано пользовательским вводом ;-) Вы понимаете, куда я иду с этим? С философской точки зрения нет никакого фундаментального способа решить, было ли изменение сделано вашим пользователем или кем-то еще.
Если вы действительно хотите «любых изменений, которые происходят между моментом, когда пользователь щелкает мышью или использует клавиатуру в этом приложении, и временем, когда приложение бездействует», вы можете реализовать это:
InputManager.Current.PreNotifyInput += (sender, e) =>
{
_userInput = true;
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
{
_userInput = false;
}));
};
Но в этом случае, если у вас есть данные, поступающие динамически из внешнего источника, они могут ошибочно считаться пользовательским вводом.
Другой подход - перевернуть ваш вверх дном: каждый раз, когда вы обновляете данные из внешнего источника данных, установите флаг, говорящий, что вы делаете это. Затем каждый раз, когда вы видите изменения с не установленным флагом, вы предполагаете, что это было взаимодействие с пользователем. Это может быть проще для реализации, если вы сможете обеспечить обновление всех ваших внешних данных выше DispatcherPriority.Render.