2010-05-02 257 views
4

我有一个简单的WM7页面,其中包含TextBox。此外,我将EventToCommand(a RelayCommand<string>)分配给此TextBox,对TextChanged事件作出反应。为了测试pourposes,我在页面的代码中添加了其他方法TextBox_TextChanged。命令和TextBox_TextChanged都用文本框内容打印消息框。MVVM Light太快:)

TextBox的初始值是"ABC"。然后按D和:

  1. TextBox_TextChanged打印ABCD
  2. 该命令打印ABC。 D缺失。

为什么命令如此之快?

命令声明:

public RelayCommand<string> TextChanged {get; private set;} 

命令初始化:

TextChanged = new RelayCommand<string>((s) => MessageBox.Show(s)); 

命令绑定:

<TextBox x:Name="SearchTextBox" Margin="10,0" TextWrapping="Wrap" Text="{Binding SearchString, Mode=TwoWay}" FontStyle="Italic" TextChanged="SearchTextBox_TextChanged" > 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="TextChanged"> 
      <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding TextChanged, Mode=OneWay}" CommandParameter="{Binding Text, ElementName=SearchTextBox}"/> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</TextBox> 
+0

你可以发布你的代码吗?没有看到它们是如何结合在一起的,很难确定地知道。 – Oded 2010-05-02 10:08:32

+0

这里有问题吗? – 2010-05-02 10:27:16

+0

作者:WM7你的意思是Windows Phone 7? – 2010-05-02 10:54:57

回答

6

我无法重现此问题。我曾尝试使用EventToCommand和行为(它只是监听TextChanged事件)。

没有看到代码我怀疑这可能与您如何获得搜索框的文本或其他地方的逻辑错误有关。

这是我如何使用EventToCommand一个片段:

<TextBox Name="SearchTextBox"> 
    <i:Interaction.Triggers> 
    <i:EventTrigger EventName="TextChanged"> 
     <cmd:EventToCommand Command="{Binding TestTextChangedCommand,Mode=OneWay}" CommandParameter="{Binding Path=Text, ElementName=SearchTextBox}"/> 
    </i:EventTrigger> 
    <i:Interaction.Triggers> 
</TextBox> 

在视图模型

m_TestTextChangedCommand = new RelayCommand<string>(val => System.Diagnostics.Debug.WriteLine(val)); 

正如你可以看到我用了一个commandparameter传递文本框的视图模型的价值。通过这种方式,viewmodel不必知道文本框就可以获取文本值。

这种方法另一种方法是使用行为和双向绑定更新的属性:

<TextBox Name="SearchTextBox" Text="{Binding TextInViewModel, Mode=TwoWay}" > 
    <i:Interaction.Behaviors> 
    <sc:UpdateOnTextChangedBehavior/> 
    </i:Interaction.Behaviors> 
</TextBox> 

UpdateOnTextChangedBehavior类:

public class UpdateOnTextChangedBehavior : Behavior<TextBox> 
    { 
     protected override void OnAttached() 
     { 
      base.OnAttached(); 

      this.AssociatedObject.TextChanged += 
       new TextChangedEventHandler(AssociatedObject_TextChanged); 
     } 

     void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e) 
     { 
      System.Diagnostics.Debug.WriteLine(((TextBox)sender).Text); 
      BindingExpression binding = 
       this.AssociatedObject.GetBindingExpression(TextBox.TextProperty); 
      if (binding != null) 
      { 
       binding.UpdateSource(); 
      } 
     } 

     protected override void OnDetaching() 
     { 
      base.OnDetaching(); 

      this.AssociatedObject.TextChanged -= 
       new TextChangedEventHandler(AssociatedObject_TextChanged); 
     } 
    } 

什么上面所做的是模拟天生的桌面WPF的行为BindingUpdateSourceTrigger=PropertyChanged,这在Silverlight中不存在。那么会发生什么,只要你输入文本框TextInViewModel属性就会得到更新。这个属性并不是一个DependencyProperty,它可能只是一个正常的CLR属性。

+0

谢谢!它像一个魅力,它帮助了我很多 – J4N 2011-11-28 14:19:00

0

一些代码,我起诉(类似于你的命令为例):

命令声明:

public RelayCommand<string> TextChanged {get; private set;} 

命令初始化:

TextChanged = new RelayCommand<string>((s) => MessageBox.Show(s)); 

命令绑定:

<TextBox x:Name="SearchTextBox" Margin="10,0" TextWrapping="Wrap" Text="{Binding SearchString, Mode=TwoWay}" FontStyle="Italic" TextChanged="SearchTextBox_TextChanged" > 
<i:Interaction.Triggers> 
    <i:EventTrigger EventName="TextChanged"> 
     <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding TextChanged, Mode=OneWay}" CommandParameter="{Binding Text, ElementName=SearchTextBox}"/> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

由于某些原因,messagebox显示一个字符延迟一个字符。

+0

欢迎来到stackoverflow!请注意,您不应在此回复答案,要么使用评论或编辑原始帖子,答案没有任何顺序。 – 2010-05-03 09:40:02

1

这适用于通过RelayCommand参数的TextBox。督察 - RelayCommand<TextBox>

<TextBox Height="72" HorizontalAlignment="Left" Margin="8,136,0,0" Name="txtFilter" Text="" VerticalAlignment="Top" Width="460" > 
     <interactivity:Interaction.Triggers> 
      <interactivity:EventTrigger EventName="TextChanged"> 
       <cmd:EventToCommand Command="{Binding SearchedTextChanged}" CommandParameter="{Binding ElementName=txtFilter}" /> 
      </interactivity:EventTrigger> 
     </interactivity:Interaction.Triggers> 
    </TextBox> 

public RelayCommand<TextBox> SearchedTextChanged { get; set; } 

SearchedTextChanged = new RelayCommand<TextBox>(OnSearchedTextChanged); 

private void OnSearchedTextChanged(TextBox val) 
    { 
     if (val != null) 
     { 
      System.Diagnostics.Debug.WriteLine(val.Text); 
     } 
    } 
1

我也有类似的问题,并发现数据绑定操作不总是触发,直到文本框失去焦点。但是,命令将立即开始。

如果要在使用该值之前确保数据绑定已发生,可以在控件上调用BindingExpression.UpdateSource()方法。尝试是这样的:

var bindTarget = SearchTextBox.GetBindingExpression(TextBox.TextProperty); 
bindTarget.UpdateSource(); 

为了避免直接在您的视图模型指的是你的文本框(因为你应该MVVM),你可以使用FocusManager.GetFocusedElement()。这在处理ApplicationBar按钮时特别有用,因为它们在使用时似乎没有获得焦点。