如何使用mvvm模式绑定到CLR事件?
对于路由事件,我正在使用Cinch框架中的EventToCommandTrigger,这很有用。
我从Expression Blend Samples中查看了Behaviors and Effects,看起来我应该使用DataEventTrigger,但样本有点令人困惑。
我希望IsVisibleChanged事件触发我的IsVisibleChangedCommand。我也不确定在ViewModel中需要使用哪些代码来支持它。
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<framework:EventToCommandTrigger Command="{Binding SelectedMenuItemChangedCommand}"
CommandParameter="{Binding SelectedValue, ElementName=lstClusters}" />
</i:EventTrigger>
<framework:DataEventTrigger EventName="IsVisibleChanged"
Source="{Binding IsVisibleChangedCommand}">
</framework:DataEventTrigger>
</i:Interaction.Triggers>
答案 0 :(得分:7)
您可以使用Expression Blend SDK来调用命令以响应一般事件,但我的经验是,并非EventTrigger都支持所有事件。
例如,这似乎有效:
<Label Content="LabelText">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseMove">
<i:InvokeCommandAction Command="{Binding IsVisibleChangedCommand, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Label>
但这不是:
<Label Content="LabelText">
<i:Interaction.Triggers>
<i:EventTrigger EventName="IsVisibleChanged">
<i:InvokeCommandAction Command="{Binding IsVisibleChangedCommand, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Label>
我不知道为什么,但Blend SDK似乎不喜欢IsVisible属性。您可以执行类似的操作,但使用Visibility(而不是IsVisible)和PropertyChangedTrigger,如下所示:
<Label x:Name="label1" Content="LabelText">
<i:Interaction.Triggers>
<ei:PropertyChangedTrigger Binding="{Binding Visibility, ElementName=label1}">
<i:InvokeCommandAction Command="{Binding IsVisibleChangedCommand, Mode=OneWay}"/>
</ei:PropertyChangedTrigger>
</i:Interaction.Triggers>
</Label>
BTW - 以下是命名空间:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
此外,这是针对您的特定问题的另一种解决方案,不需要Blend SDK:
不是直接将事件绑定到命令,而是可以将对象的Visibility属性绑定到viewmodel属性,并从属性setter执行命令,如下所示:
查看:
<UserControl x:Class="SampleApp.Views.EventBindingDemoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="200" Width="200">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</UserControl.Resources>
<Grid>
<Label Content="LabelText" Visibility="{Binding Path=ElementIsVisible, Mode=TwoWay, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<!-- The rest of your view here -->
</Grid>
</UserControl>
ViewModel(ViewModelBase应该实现INotifyPropertyChanged和OnPropertyChanged(string propertyName)):
public class EventBindingDemoViewModel : ViewModelBase
{
private bool ElementIsVisibleField = true; // or false if it should initially be hidden
public bool ElementIsVisible
{
get { return this.ElementIsVisibleField; }
set
{
if (this.ElementIsVisibleField != value)
{
this.ElementIsVisibleField = value;
this.OnPropertyChanged("ElementIsVisible");
// Execute command
this.IsVisibleChangedCommand.Execute(null);
}
}
}
public ICommand IsVisibleChangedCommand;
// The rest of your viewmodel here
}
无论哪种方式都应该有效。