2010-05-02 7 views
4

У меня есть простая страница WM7 с TextBox. В дальнейшем я назначил EventToCommand (a RelayCommand<string>) на этот TextBox, отреагировав на событие TextChanged. Для тестирования личинок я сделал дополнительный код 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

+0

есть вопрос здесь? –

+0

Под WM7 вы имеете в виду Windows Phone 7? –

ответ

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> 

В ViewModel

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

Как вы можете видеть, что я использовал CommandParameter передать значение текстового поля к ViewModel. Таким образом, viewmodel не должен знать о текстовом поле, чтобы получить текстовое значение.

Альтернатива этого подхода будет использовать поведение и TwoWay привязки обновить свойство:

<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 Binding с UpdateSourceTrigger=PropertyChanged, которого нет в Silverlight. Итак, что произойдет, всякий раз, когда вы вводите текстовое поле TextInViewModel, свойство будет обновляться. Это свойство не должно быть DependencyProperty, это может быть обычное свойство CLR.

+0

Спасибо! Он работает как шарм, он мне очень помог – J4N

0

Некоторые код, я подал в суд (по аналогии с вашим Command например):

Командная декларация:

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> 

По некоторым причинам в окне сообщений отображается строка с одной задержкой символа.

+0

Добро пожаловать в stackOverflow! Обратите внимание, что вы не должны публиковать ответы, как ответы здесь, либо использовать комментарии, либо редактировать исходное сообщение, а ответы не имеют никакого порядка. –

1

Это работает с TextBox через параметр RelayCommand. IOW - 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

У меня был подобный вопрос и обнаружил, что операция привязки не всегда срабатывает до тех пор, пока TextBox теряет фокус. Однако команда немедленно сработает.

Если вы хотите гарантировать, что привязка данных произошла до того, как вы используете значение, вы можете вызвать метод BindingExpression.UpdateSource() на свой контроль. Попробуйте что-то вроде этого:

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

Чтобы избежать ссылок на ваш TextBox непосредственно в ViewModel (как следует с MVVM), вы можете использовать FocusManager.GetFocusedElement(). Это особенно полезно при работе с кнопками ApplicationBar, поскольку они, похоже, не получают фокуса при использовании.