问题
I'm trying to put together a very simple example app, but it is not working as intented.
Here is the scenario:
Caliburn.Micro, MVVM, Silverlight 5.0 - simple Conductor example from https://caliburnmicro.codeplex.com/wikipage?title=Screens%2c%20Conductors%20and%20Composition&referringTitle=Documentation (Simple Navigation)
I just put together a live example: https://db.tt/kTIjKvRx
-> hit enter in textbox (messagebox displays 1x)
-> go to master and go back to login
-> hit enter in textbox (messagebox displays 2x!)
ShellViewModel
public class ShellViewModel : Conductor<object> {
public ShellViewModel() {
ShowLogin();
}
public void ShowLogin() {
ActivateItem(new LoginViewModel());
}
public void ShowMaster() {
ActivateItem(new MasterViewModel());
}
}
EDIT:
Same results with this:
public class ShellViewModel : Conductor<object> {
public ShellViewModel() {
LoginModel = new LoginViewModel();
MasterModel = new MasterViewModel();
ShowLogin();
}
public LoginViewModel LoginModel { get; set; }
public MasterViewModel MasterModel { get; set; }
public void ShowLogin() {
ActiveItem = LoginViewModel;
}
public void ShowMaster() {
ActiveItem = MasterViewModel;
}
}
ShellView
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" x:Class="Hele.ShellView"
d:DesignWidth="438" d:DesignHeight="200">
<Grid>
<StackPanel Orientation="Vertical" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button x:Name="ShowLogin" Width="100" Height="30" Content="Login"/>
<Button x:Name="ShowMaster" Width="100" Height="30" Content="Master"/>
<ContentControl x:Name="ActiveItem" " />
</Grid>
</UserControl>
LoginView
<UserControl ... >
<Grid x:Name="LayoutRoot">
<StackPanel>
<TextBlock>Login</TextBlock>
<TextBox x:Name="Message" Text="{Binding Message, Mode=TwoWay}" >
<i:Interaction.Triggers>
<iex:KeyTrigger Key="Enter">
<cal:ActionMessage MethodName="Login" />
</iex:KeyTrigger>
</i:Interaction.Triggers>
</TextBox>
</StackPanel>
</Grid>
</UserControl>
LoginViewModel
public class LoginViewModel : Screen
{
public string Message { get; set; }
public void Login()
{
MessageBox.Show("login messagebox");
}
}
MasterView and MasterViewModel are just empty, nothing interesting there.
The above example just works fine, after clicking on Login button shows login view, on Master shows master view.
In the Login View there is a textbox which has an event trigger. After hitting Enter key, it calls a method from viewmodel and displays a messagebox.
The problem:
When going to master view and going back to login end hitting Enter - it shows the messagebox twice!
Going to master and again back -> it will display it 3x.. and so on.
I think the Trigger should fire only once. How can we achieve this behavior?
回答1:
I think it's because your doing the ActivateItem each time your loading the view which rebinds the event handlers to the view. Try setting the ActiveItem property instead (which the ContentControl with x:Name="ActiveItem" is bound to). Also try using public variables to hold your view models:
public class ShellViewModel : Conductor<object> {
public ShellViewModel() {
ShowLogin();
}
public LoginViewModel { get; set; }
public MasterViewModel { get; set; }
public void ShowLogin() {
ActiveItem = LoginViewModel;
}
public void ShowMaster() {
ActiveItem = MasterViewModel;
}
}
EDIT
I was able to reproduce this and it seems to be an issue with the Expression Interactions. If I use a regular EventTrigger attached to key down it works fine:
<TextBox Width="50" Text="{Binding Message, Mode=TwoWay}" >
<i:Interaction.Triggers>
<!--<iex:KeyTrigger Key="Enter">
<cm:ActionMessage MethodName="Page1KeyPress" />
</iex:KeyTrigger>-->
<i:EventTrigger EventName="KeyDown">
<cm:ActionMessage MethodName="Page1KeyPress" >
<cm:Parameter Value="$source" />
<cm:Parameter Value="$eventArgs" />
</cm:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
public void Page1KeyPress(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
MessageBox.Show("Page 1 Key Press");
}
来源:https://stackoverflow.com/questions/20434699/caliburn-micro-conductor-trigger-action-firing-more-than-exptected