问题
I have a Button in a DataTemplate that is bound to a Command in my ViewModel. The button also has an EventTrigger that kicks off a Storyboard that hides the edit controls (of which the button is a part.)
The Storyboard works fine if I pick up the PreviewMouseDown event, but the Command never gets called. If I pick up the MouseDown event in my EventTrigger, the Command works, but the Storyboard doesn't execute.
How can I get both the Command and the Storyboard to execute when the button is clicked?
<Button Content="Save" Command="{Binding SaveCommand}" >
<Button.Triggers>
<EventTrigger RoutedEvent="Button.PreviewMouseDown">
<EventTrigger.Actions>
<BeginStoryboard Storyboard="{DynamicResource sbCloseTitleEdit}"/>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
</Button>
回答1:
I ended up inelegantly solving my problem by adding a code-behind file for my ResourceDictionary that contains the DataTemplate. I wasn't aware that this was possible, but found this explanation:
Is it possible to set code behind a resource dictionary in WPF for event handling?
Instead of using the EventTrigger to begin a Storyboard that hides the edit controls I added a Click handler to the code-behind. It's a bit kludgy as I have to locate the panels relative to the button clicked as that is the only reference available, but it works.
Still looking for a better solution if anyone has one.
回答2:
Ive tried your code, and I find that it works OK with the event trigger on PreviewMouseDown
, its just that the command is executed first, then the animation fires.
Heres my resources
<Storyboard x:Key="sbCloseTitleEdit">
<ColorAnimation Storyboard.TargetProperty="(Rectangle.Fill).Color"
To="Blue" Duration="0:0:3" Storyboard.TargetName="rect" >
</ColorAnimation>
</Storyboard>
my xaml
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button Content="Save" Command="{Binding SaveCommand}" >
<Button.Triggers>
<EventTrigger RoutedEvent="Button.PreviewMouseDown">
<EventTrigger.Actions>
<BeginStoryboard
Storyboard="{StaticResource sbCloseTitleEdit}"/>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
</Button>
<Rectangle Name="rect" Width="30" Height="30"
Grid.Column="1" Fill="Red" />
</Grid>
and my view model
public class MainViewModel
{
public ActionCommand SaveCommand { get; private set; }
public MainViewModel()
{
SaveCommand = new ActionCommand();
}
}
public class ActionCommand : ICommand
{
public void Execute(object parameter)
{
// gets fired if event trigger is preview mode
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
are you sure you havent missed something ?
回答3:
I achieved this by invoking the command within the eventtrigger along with the other action you want to trigger:
<Button Command="{Binding AcceptCommand}" Content="Accept">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding AcceptCommand}"/>
<triggers:UpdatePropertyAction TargetObject="{Binding RelativeSource={RelativeSource AncestorType={x:Type Controls:ChildWindow}, Mode=FindAncestor}}" TargetProperty="DialogResult" Value="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
来源:https://stackoverflow.com/questions/3908526/how-to-use-both-command-and-eventtrigger-in-datatemplate-button