4

.を持つ単純な WM7 ページがありTextBoxます。さらに、イベントに反応してEventToCommand(a RelayCommand<string>) を thisに割り当てました。目的をテストするために、ページの分離コードに追加のメソッドを作成しました。コマンドとテキストボックスの内容を含むメッセージボックスを出力します。TextBoxTextChangedTextBox_TextChangedTextBox_TextChanged

の初期値は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>
4

4 に答える 4

6

この動作を再現できません。EventToCommand と Behaviour (単に 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));

ご覧のとおり、コマンド パラメータを使用して、テキスト ボックスの値をビューモデルに渡しました。このように、ビューモデルはテキスト値を取得するためにテキストボックスについて知る必要はありません。

このアプローチに代わる方法は、動作と 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);
        }
    }

上記が行うことは、Silverlight にはないデスクトップ WPF の動作を模倣することですBindingUpdateSourceTrigger=PropertyChangedテキストボックスのTextInViewModelプロパティに入力するたびに、何が起こるかが更新されます。DependencyPropertyこのプロパティは である必要はありません。通常の CLR プロパティでかまいません。

于 2010-05-02T10:53:56.807 に答える
1

これは、RelayCommand のパラメーターを介して TextBox で機能します。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);
        }
    }
于 2010-11-15T13:35:07.477 に答える
1

同様の問題があり、TextBox がフォーカスを失うまで、データバインディング操作が常に起動するとは限らないことがわかりました。ただし、コマンドはすぐに起動します。

値を使用する前にデータバインディングが発生したことを保証したい場合はBindingExpression.UpdateSource()、コントロールでメソッドを呼び出すことができます。次のようなことを試してください:

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

ViewModel で TextBox を直接参照しないようにするには (MVVM の場合と同様)、 を使用できますFocusManager.GetFocusedElement()。これは、ApplicationBar ボタンを使用してもフォーカスを受け取らないように見えるため、これらのボタンを扱う場合に特に便利です。

于 2011-12-09T23:38:16.560 に答える
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>

いくつかの理由で、メッセージボックスには1文字の遅延のある文字列が表示されます。

于 2010-05-03T09:07:20.033 に答える