2014-01-06 26 views
0

我们使用文本框来显示从IO系统接收到的数据。如果用户在文本框中输入一些数据,则该值将写入IO系统。TextBox - 识别输入的数据是否由用户

我们使用OnTextChanged事件将用户输入的数据写入IO系统。

问题是,当我们将从IO系统收到的值更新到文本框(从代码)时,我们得到了这个事件。

是否有可能知道文本框的值是由用户还是通过使用代码更改?

回答

0

我不知道这是否适合您的情况,但您可以尝试使用KeyUpKeyDown事件。只有当用户输入某些内容到TextBox时,才会引发该事件,如果文本被代码更改,则不会引发该事件。 KeyUpTextChanged之后引发的事件,因此您将在TextBox中准备好新输入的文本。在TextChanged之前提出KeyDown,因此您需要在TextBox中追加当前文本并按下字符/键。使用KeyUp/KeyDown的缺点是,如果用户使用上下文菜单通过复制/剪切粘贴输入文本(右击>粘贴),您将不会收到通知。解决方法是禁用默认的上下文菜单如下(或通过风格):

<TextBox ContextMenu="{x:Null}"/> 

用户仍然可以使用键盘快捷键做剪切/复制/粘贴,并且按下某些键盘按键的程序将得到通知。

希望这个想法适合您的需求。

0

由于我不确定你到底是什么,所以我会给你两个解决方案。

解决方案1:使用MVVM进行绑定。

而不是拾取OnTextChanged事件,将TextBox绑定到您的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方法支持字段,我还是叫OnPropertyChange以更新绑定到TextBox。 TextBox的xaml将是

<TextBox Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged}" /> 

如果您正在保存键入内容,UpdateSourceTrigger非常重要。

尽管这是我的首选解决方案,但大量文本可能会导致性能问题。

方案2:OnTextChanged

您已经在处理一个事件,处理所有相关的键盘事件(大概只有KEYDOWN)。你的文本框的XAML将

<TextBox x:Name="EntryControl" PreviewKeyDown="UIElement_OnPreviewKeyDown" PreviewKeyUp="UIElement_OnPreviewKeyUp" KeyDown="UIElement_OnKeyDown" KeyUp="UIElement_OnKeyUp" TextChanged="TextBoxBase_OnTextChanged" /> 

如果每个事件输出它的名字到输出窗口,你会得到的事件按以下顺序

  • UIElement_OnPreviewKeyDown
  • UIElement_OnKeyDown
  • TextBoxBase_OnTextChanged
  • UIElement_OnPreviewKeyUp
  • UIElement_OnKeyUp

通过在OnKeyDown事件中设置一个布尔值并在OnTextChanged事件中检查它,您可以测试键盘输入。

注意:当按住一个键,你会得到多的KeyDown事件到一个KEYUP事件。事件中被解雇的顺序是

-UIElement_OnPreviewKeyDown -UIElement_OnKeyDown -TextBoxBase_OnTextChanged -UIElement_OnPreviewKeyDown -UIElement_OnKeyDown -TextBoxBase_OnTextChanged -UIElement_OnPreviewKeyDown -UIElement_OnKeyDown -TextBoxBase_OnTextChanged -UIElement_OnPreviewKeyUp -UIElement_OnKeyUp

所以解决方案仍然存在。

测试出

的解决方案,如果您正在寻找尝试在一个示例应用程序的2种情况,对于我的例子XAML是

<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"; } 
} 

ViewModel在回答开始时显示完整。

适当的异常处理已被排除赘述。

我希望这有助于。

相关问题