假设我有一个WPF TextBox
:
<TextBox Text="{Binding Foo}" />
在属性Foo
由TextBox
更新(即由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();
}