更新绑定的源之后,如何执行ICommand



假设我有一个WPF TextBox:

<TextBox Text="{Binding Foo}" />

在属性FooTextBox更新(即由TextBox而不是某些其他控件或代码专门更新)之后,是否有方法执行某些ICommand

我不想使用绑定的SourceUpdated事件,因为我想避免"代码隐藏"。

你知道MVVM警察不会来抓你吗?使用事件来命令etc本质上只是在XAML中编码,而不是在C#中编码。无论哪种方式,您都需要将事件挂接到命令,因为控件不会为您想要的内容公开命令。

我想这就是你想要的,如果我走错了轨道,请告诉我:

您想知道Foo的更新何时来自文本框,何时仅来自文本框。也就是说,如果Foo的更新来自一些你不想运行命令的代码,对吗?

如果是:

        <TextBox Name="Fred" Text="{Binding Foo, NotifyOnSourceUpdated=True}" SourceUpdated="Fred_SourceUpdated"/>

然后在"邪恶"代码背后有:

private void Fred_SourceUpdated(object sender, DataTransferEventArgs e)
    {
    }

在该方法中,您可以将视图的数据上下文强制转换到视图模型中,并调用所需的任何命令。如果有其他内容更新Foo,则不会调用源更新事件。

如果你真的不想像你在OP中提到的那样隐藏代码,那么你可以做一个附加的行为,但对于"胡说八道"的要求来说,这太过分了。事实上,您的逻辑取决于更改是否来自文本框,这意味着您的视图已经不仅仅是一个视图。这种方法仍然允许您在VM中完全测试命令代码。

第二次编辑

您还可以通过事件到命令来查看XAML中使用源更新的事件,而不是文本更改的

您可以尝试创建一个可以执行任何您想执行的操作的方法,并在调用raisepropertychanged()后调用该方法。例如

 public void MyMethod() 
  {
      //Do whatever;
  }

然后在您的属性getter setter中:

  public string MyText 
  {
    get { return _MyText; }
    set 
    {
       _MyText = value;
       RaisePropertyChanged("MyText")
       // THen call that method
       MyMehtod();
    }
   }

语法可能不好,我最近习惯做vb了。希望这能有所帮助,但如果你需要其他选择,还有其他方法。

编辑2:

<Textbox Text="{Binding Foo}">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="TextChanged">
      <i:InvokeCommandAction Command="{Binding TextChangedCommand}" />
    </i:EventTrigger>
 </i:Interaction.Triggers>

TextChangedCommand在视图模型中的位置

不确定TextChanged是否是EventName,我不会记住所有可用的事件类型

假设您已经实现了INotifyPropertyChanged,那么您只需要处理PropertyChanged事件。您可以在事件处理程序中执行该命令。此事件处理程序位于ViewModel中(而不是代码隐藏)。

编辑

以下是MVVM Light中EventToCommand行为的工作方式示例。您可以使用它来允许使用命令处理任何事件。

<Rectangle Fill="White"
           Stroke="Black"
           Width="200"
           Height="100">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter">
            <cmd:EventToCommand Command="{Binding TestCommand,
                                          Mode=OneWay}"
               CommandParameter="{Binding Text,
                                  ElementName=MyTextBox,
                                  Mode=OneWay}"
               MustToggleIsEnabledValue="True" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Rectangle>

编辑2

另一个想法是在通过代码更改Foo时始终使用一种方法。这样,您就知道,对Foo的任何不使用该方法的更改都必须由用户更改。

private bool _isFooUpdating;
private void SetFoo(string value)
{
    _isFooUpdating = true;
    Foo = value;
    _isFooUpdating = false;
}
public string Foo
{
    get { return _foo; }
    set
    {
        if (_foo = value) return;
        _foo = value;
        OnFooChanged();
        OnPropertyChanged("Foo");
    }
}
private void OnFooChanged()
{
    if (_isFooUpdating) return;
    FooChangedCommand.Execute();
}

最新更新