Silverlight MVVM灯光太快:)

Silverlight MVVM灯光太快:),silverlight,windows-phone-7,mvvm,command,mvvm-light,Silverlight,Windows Phone 7,Mvvm,Command,Mvvm Light,我有一个带有文本框的简单WM7页面。此外,我将事件分配给命令(一个RelayCommand)给这个文本框,对文本更改事件作出反应。为了测试pourposes,我在页面的代码隐藏中添加了额外的方法TextBox\u TextChanged。命令和TextBox\u TextChanged打印包含TextBox内容的消息框 文本框的初始值为“ABC”。然后我按D键,然后: TextBox\u TextChanged打印ABCD 该命令打印ABC。D不见了 为什么命令这么快 命令声明: public

我有一个带有
文本框的简单WM7页面。此外,我将
事件分配给命令
(一个
RelayCommand
)给这个
文本框
,对
文本更改
事件作出反应。为了测试pourposes,我在页面的代码隐藏中添加了额外的方法
TextBox\u TextChanged
。命令和
TextBox\u TextChanged
打印包含TextBox内容的消息框

文本框的初始值为
“ABC”
。然后我按D键,然后:

  • TextBox\u TextChanged
    打印
    ABCD
  • 该命令打印
    ABC
    。D不见了
  • 为什么命令这么快

    命令声明:

    public RelayCommand<string> TextChanged {get; private set;}
    
        public RelayCommand<string> TextChanged {get; private set;}
    
    public RelayCommand TextChanged{get;private set;}
    
    命令初始化:

    TextChanged = new RelayCommand<string>((s) => MessageBox.Show(s));
    
    TextChanged = new RelayCommand<string>((s) => MessageBox.Show(s));
    
    TextChanged=newrelaycommand(=>MessageBox.Show));
    
    命令绑定:

    <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>
    
    <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>
    

    我无法重现这种行为。我尝试过使用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));
    
    m_TestTextChangedCommand=newrelaycommand(val=>System.Diagnostics.Debug.WriteLine(val));
    
    如您所见,我使用commandparameter将文本框的值传递给viewmodel。这样,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);
            }
        }
    
    公共类UpdateOnTextChangedBehavior:行为
    {
    受保护的覆盖无效附加()
    {
    base.onatached();
    this.AssociatedObject.TextChanged+=
    新的TextChangedEventHandler(关联对象\u TextChanged);
    }
    无效关联对象\u TextChanged(对象发送者,textchangedventargs e)
    {
    System.Diagnostics.Debug.WriteLine(((文本框)sender.Text);
    BindingExpression绑定=
    this.AssociatedObject.GetBindingExpression(TextBox.TextProperty);
    if(绑定!=null)
    {
    binding.UpdateSource();
    }
    }
    附加时受保护的覆盖无效()
    {
    base.OnDetaching();
    this.AssociatedObject.TextChanged-=
    新的TextChangedEventHandler(关联对象\u TextChanged);
    }
    }
    
    上面所做的是模仿桌面WPF
    UpdateSourceTrigger=PropertyChanged
    绑定的行为,这在Silverlight中是缺失的。那么,每当您在文本框中键入
    TextInViewModel
    属性时,将会发生什么情况呢。此属性不必是
    DependencyProperty
    ,它可以是普通的CLR属性。

    我使用的一些代码(类似于您的命令示例):

    命令声明:

    public RelayCommand<string> TextChanged {get; private set;}
    
        public RelayCommand<string> TextChanged {get; private set;}
    
    public RelayCommand TextChanged{get;private set;}
    
    命令初始化:

    TextChanged = new RelayCommand<string>((s) => MessageBox.Show(s));
    
    TextChanged = new RelayCommand<string>((s) => MessageBox.Show(s));
    
    TextChanged=newrelaycommand(=>MessageBox.Show));
    
    命令绑定:

    <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>
    
    <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显示一个带有一个字符延迟的字符串。

    这通过RelayCommand的参数与TextBox一起工作。IOW-
    RelayCommand

    
    public RelayCommand SearchedTextChanged{get;set;}
    SearchedTextChanged=新的RelayCommand(OnSearchedTextChanged);
    SearchedTextChanged上的私有无效(文本框val)
    {
    如果(val!=null)
    {
    系统.诊断.调试.写入线(val.Text);
    }
    }
    
    我也遇到了类似的问题,发现在文本框失去焦点之前,数据绑定操作并不总是启动。然而,命令将立即开火

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

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

    为了避免在ViewModel中直接引用文本框(MVVM应该这样做),可以使用
    FocusManager.GetFocusedElement()
    。这在处理应用程序栏按钮时特别有用,因为它们在使用时似乎没有焦点。

    您能发布代码吗?如果看不到它们是如何连接在一起的,就很难确定。WM7是指Windows Phone 7吗?为galasoft mvvm light support添加mvvm light标记:)@Sky-是的,他想知道为什么两个代表响应同一事件会产生不同的结果。当附加了事件处理程序时,该命令似乎在绑定发生之前运行。与仅供参考一样,TextBox.TextChanged事件在A)TextBox失去焦点或B)文本通过文本属性或自动更正事件更改之前不会触发。可能是TextChanged事件有两个侦听器会产生副作用,导致它们报告不同的事件。欢迎使用stackOverflow!请注意,您不应该在这里发布回复作为答案,或者使用评论或编辑原始帖子,答案没有任何顺序。