我正在使用InputManager来检查控件的更改是由用户还是代码完成的。这种方法很好,除非用户使用上下文菜单进行剪切/复制/粘贴。如果用户在文本框中执行ctrl + v,则InputManager会正确注意它。但是,如果粘贴是从文本框的上下文菜单中完成的,则InputManager永远不会触发PreNotifyInput或PostNotifyInput事件。谁知道为什么?或者如何检测这些用户操作?以下是一份工作样本。当用户在上面的文本框中使用剪切/复制/粘贴菜单时,下面的文本块永远不会更新,因为PreNotifyInput永远不会触发。
XAML:
<Window x:Class="InputMgrDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<StackPanel>
<TextBox TextChanged="TextBox_TextChanged" />
<TextBlock Name="_text" />
</StackPanel>
</Window>
代码背后:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace InputMgrDemo
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
InputManager.Current.PreNotifyInput += ((sender, e) => _userInput = true);
InputManager.Current.PostNotifyInput += ((sender, args) => _userInput = false);
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (_userInput)
{
_text.Text = (sender as TextBox).Text;
}
}
private bool _userInput;
}
}
答案 0 :(得分:2)
实际上,PreNotifyInput事件会触发MouseLeftButtonUp事件,但PostNotifyInput会在实际粘贴发生之前触发。
以下是操作顺序:
您的PostNotifyInput事件处理程序被称为,因为处理了MouseLeftButtonUp事件
Dispatcher安排的任何渲染都会完成
Dispatcher在MenuItem中调用回调
在WPF中,“用户输入”的影响可以通过调度程序回调等任意延迟,因此您无法知道更改是否是由用户输入引起的。
事实上,从理论上讲,这一般都是正确的。请考虑以下情况:
显然,在每种情况下,变化都是由用户输入引起的;-)你看到我要去哪里吗?从哲学角度来说,没有根本的方法来决定您的用户或其他人是否进行了更改。
如果您真正想要的是“在用户单击鼠标或在此应用程序中使用键盘与应用程序空闲时间之间发生的任何更改”,您可以实现此目的:
InputManager.Current.PreNotifyInput += (sender, e) =>
{
_userInput = true;
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() =>
{
_userInput = false;
}));
};
但是在这种情况下,如果您有来自外部Feed的动态数据,则可能会错误地将其视为用户输入。
另一种方法是将您的内容颠倒过来:每当您从外部数据源刷新数据时,请设置一个标记,说明您正在这样做。然后,只要您看到未设置该标志的更改,您就会认为这是用户交互。如果您可以确保所有外部数据更新都发生在DispatcherPriority.Render之上,那么这可能更容易实现。