【问题标题】:Caliburn.Micro Conductor: Trigger/Action firing more than exptectedCaliburn.Micro Conductor:触发/动作触发超出预期
【发布时间】:2013-12-06 22:28:38
【问题描述】:

我正在尝试组合一个非常简单的示例应用程序,但它并没有按预期工作。

这是场景:

Caliburn.Micro、MVVM、Silverlight 5.0 - 来自https://caliburnmicro.codeplex.com/wikipage?title=Screens%2c%20Conductors%20and%20Composition&referringTitle=Documentation 的简单导体示例(简单导航)

我只是整理了一个活生生的例子: 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());
    }
}

编辑:

同样的结果:

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>

登录查看

<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>

登录视图模型

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.

上面的例子工作正常,点击登录按钮后显示登录视图,在主上显示主视图。

在登录视图中有一个带有事件触发器的文本框。按 Enter 键后,它会从 viewmodel 调用一个方法并显示一个消息框。

问题:

当转到主视图并返回登录端时按 Enter - 它会显示消息框两次!

去 master 然后再回来 -> 它将显示 3x.. 等等。

我认为触发器应该只触发一次。我们如何才能实现这种行为?

【问题讨论】:

    标签: c# silverlight silverlight-5.0 caliburn.micro


    【解决方案1】:

    我认为这是因为您每次加载视图时都会执行 ActivateItem,这会将事件处理程序重新绑定到视图。尝试设置 ActiveItem 属性(与 x:Name="ActiveItem" 绑定的 ContentControl )。还可以尝试使用公共变量来保存您的视图模型:

    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;
        }
    }
    

    编辑

    我能够重现这一点,这似乎是表达式交互的问题。如果我使用附加到按键的常规 EventTrigger 它可以正常工作:

            <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");
        }
    

    【讨论】:

    • 不幸的是相同的结果。正如您所建议的,我正在使用 now 属性,并将它们设置在构造函数中 + using ActiveItem = ...
    猜你喜欢
    • 1970-01-01
    • 2011-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-25
    • 2013-07-19
    • 2013-01-29
    • 2013-05-01
    相关资源
    最近更新 更多