Wpf 文本框-标识输入的数据是否由用户输入
我们使用一个文本框来显示从IO系统接收到的数据。如果用户在文本框中输入一些数据,该值将写入IO系统 我们使用ContextChanged事件将用户输入的数据写入IO系统 问题是,当我们将从IO系统接收到的值更新到文本框(从代码)时,会发生此事件Wpf 文本框-标识输入的数据是否由用户输入,wpf,wpf-controls,Wpf,Wpf Controls,我们使用一个文本框来显示从IO系统接收到的数据。如果用户在文本框中输入一些数据,该值将写入IO系统 我们使用ContextChanged事件将用户输入的数据写入IO系统 问题是,当我们将从IO系统接收到的值更新到文本框(从代码)时,会发生此事件 是否可以知道文本框的值是由用户更改的还是通过使用代码更改的?我不知道这是否适合您的情况,但您可以尝试使用KeyUp或KeyDown事件。仅当用户向TextBox键入内容时才会引发该事件,而当文本被代码更改时不会引发该事件KeyUp事件在TextChang
是否可以知道文本框的值是由用户更改的还是通过使用代码更改的?我不知道这是否适合您的情况,但您可以尝试使用
KeyUp
或KeyDown
事件。仅当用户向TextBox键入内容时才会引发该事件,而当文本被代码更改时不会引发该事件KeyUp
事件在TextChanged
之后引发,因此您可以在文本框中准备好新键入的文本。和KeyDown
在TextChanged
之前引发,因此您需要在文本框中添加当前文本并按下字符/键。使用KeyUp
/KeyDown
的缺点是,如果用户使用上下文菜单(右键单击>粘贴)通过复制/剪切粘贴输入文本,则不会收到通知。解决方法是禁用默认上下文菜单,如下所示(或通过样式):
用户仍然可以使用键盘快捷键进行剪切/复制/粘贴,当按下某些键盘键时,您的程序将收到通知
希望这个想法适合你的需要。因为我不确定你到底想要什么,所以我会给你两个解决方案 解决方案1:使用MVVM进行绑定。 将文本框绑定到viewmodel上的属性,而不是拾取ContextChanged事件。这将通过属性更新文本。当从代码更新时,调用一个方法来更新备份字段。ViewModel看起来像
public class MyViewModel : INotifyPropertyChanged
{
private string text;
public string Text
{
get { return text; }
set
{
if (value != text)
{
text = value;
OnPropertyChanged();
Debug.WriteLine("Binding Example - Keyboard entry");
}
}
}
public void AddText(string extraText)
{
this.text += extraText;
this.OnPropertyChanged("Text");
Debug.WriteLine("Binding Example - Code entry");
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
注意,即使我正在更新AddText方法中的backing字段,我仍然调用OnPropertyChange来更新到TextBox的绑定。文本框的xaml将是
<TextBox Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged}" />
ViewModel在答案的开头显示为完整
为简洁起见,已排除正确的异常处理
我希望这有帮助
<TextBox Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name="EntryControl" PreviewKeyDown="UIElement_OnPreviewKeyDown" PreviewKeyUp="UIElement_OnPreviewKeyUp" KeyDown="UIElement_OnKeyDown" KeyUp="UIElement_OnKeyUp" TextChanged="TextBoxBase_OnTextChanged" />
<Window x:Class="StackOverflow._20949513.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}, Path=ViewModel}"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<DockPanel>
<Button Content="Add Text" DockPanel.Dock="Top" Click="BindingButton_OnClick" />
<TextBox Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged}" />
</DockPanel>
<DockPanel Grid.Row="1">
<Button Content="Add Text" DockPanel.Dock="Top" Click="EventButton_OnClick" />
<TextBox x:Name="EntryControl" PreviewKeyDown="UIElement_OnPreviewKeyDown" PreviewKeyUp="UIElement_OnPreviewKeyUp" KeyDown="UIElement_OnKeyDown" KeyUp="UIElement_OnKeyUp" TextChanged="TextBoxBase_OnTextChanged" />
</DockPanel>
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
ViewModel = new MyViewModel();
InitializeComponent();
}
public MyViewModel ViewModel { get; set; }
private void BindingButton_OnClick(object sender, RoutedEventArgs e) { ViewModel.AddText("More Text"); }
private bool keyboardPressed;
private void UIElement_OnPreviewKeyDown(object sender, KeyEventArgs e) { DisplayEvent(); }
private void UIElement_OnPreviewKeyUp(object sender, KeyEventArgs e) { DisplayEvent(); }
private void UIElement_OnKeyDown(object sender, KeyEventArgs e)
{
DisplayEvent();
keyboardPressed = true;
}
private void UIElement_OnKeyUp(object sender, KeyEventArgs e) { DisplayEvent(); }
private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e)
{
try
{
if (keyboardPressed)
{
DisplayEvent("TextBoxBase_OnTextChanged from Keyboard");
}
else
{
DisplayEvent("TextBoxBase_OnTextChanged from Code");
}
}
finally
{
keyboardPressed = false;
}
}
private void DisplayEvent([CallerMemberName] string caller = null) { Debug.WriteLine(caller); }
private void EventButton_OnClick(object sender, RoutedEventArgs e) { EntryControl.Text += "More Text"; }
}