1

我正在编写一个基于 MVVM 架构的应用程序。该应用程序具有类似向导的工作流程。在我的应用程序的几个页面(视图)中,我需要一个按钮在满足特定条件时自动单击。这些视图使用根 Wizard 视图模型绑定在一起,该模型具有一个 ClickNextBtn 命令,该命令与根 Wizard 视图中的 Next 按钮相关联。所以,我需要在根向导视图中类似的东西:

<DataTrigger Binding="{Binding Path=CanAutoClickNext}" Value="True">
    <Setter Property="ClickBtn" Value="true" />
</DataTrigger>

上面示例中的属性毫无意义,但希望它有助于传达我想要做的事情。

CanAutoClickNext 布尔属性在向导视图模型中可用。

在我需要自动单击“下一步”按钮的视图之一上,我尝试将 WizardViewModel 作为参数传递给其对应的视图模型的构造函数,当它在根向导视图模型中首次实例化时,然后在其中调用 ClickNextBtn稍后实际加载视图时其中的一个方法。但这并不奏效,不足为奇。

我知道如何以编程方式单击 wpf 按钮,但是将它们全部绑定在我拥有的框架中是一个巨大的挑战。任何反馈表示赞赏。

更新: 我最终重写了 UI 设计模式(仍然是 MVVM),因此现在不必自动移动到下一页,页面中的状态会发生变化,并且一组不同的控件会变为活动状态。然后提示用户单击下一步。

4

2 回答 2

2

就像您对问题的评论一样,这应该是ViewModel调用点击处理程序的一个问题。

你如何去实现这个非常类似于这个问题的答案

现在在 MVVM 中,您应该将 Button 连接到ICommandViewModel 中的一个(如果您使用 MVVM Light 工具包,它将是RelayCommand/ RelayCommand<T>)。

现在假设ICommand你的虚拟机中的这个变量被调用NextButtonCommand

你能做的是

public bool CanAutoClickNext {
  get {
    return _canAutoClickNext;
  }

  private set {
    if (value == _canAutoClickNext)
      return;

    _canAutoClickNext = value;
    RaisePropertyChanged(() => CanAutoClickNext);

    if (_canAutoClickNext)
      NextButtonCommand.Execute(null);
  }
}

这样,当您在 VM 中的属性CanAutoClickNext设置为“True”时,VM 会ICommand自动调用 Execute 函数。这将所有逻辑处理分离到 VM 中,并使 View 在应用程序/业务逻辑方面保持 MVVM 推荐的内容。

边注

CanAutoClickNext如果该属性未绑定到视图中的任何内容,则该属性似乎是一种浪费。如果是这种情况,我建议只是摆脱该属性并ICommand.Execute(null)从逻辑适合的地方调用,而不是仅针对这种情况使用带有 INPC 的属性。

于 2013-05-08T09:19:24.603 回答
1

我会从另一个角度跟进。假设您准备好任何消息总线(IEventAggregator, IMessenger, 无关紧要)。我将使用 Caliburn.MicroIEventAggregator和命名法,因为这是我最熟悉的。现在你可能有一个非常简单的事件:

public class MoveNext
{
}

然后是向导的“主机”视图模型:

public class WizardHost : IHandle<MoveNext>
{
    private readonly IEventAggregator messageBus
    public WizardHost(IEventAggregator messageBus)
    {
        this.messageBus = messageBus;
        this.messageBus.Subscribe(this);
    }

    /here you might have the 'real' command method, e.g:
    public void GoToNextQuestion()
    {
        // do stuff
    }

    public void Handle(MoveNext message)
    {
        GoToNextQuestion();
    }
}

public class WizardPage 
{
    private readonly IEventAggregator messageBus;

    private bool shouldMoveToNext;
    public WizardPage(IEventAggregator messageBus)
    {
        this.messageBus = messageBus;

    }

    public void DoStuff()
    {
        //at some point, you might want to switch the flag or do whatever you need/want to do and:
        if(shouldMoveToNext)
            messageBus.Publish(new MoveNext());
    }
}

现在,当您DoStuff()在向导页面中时,您可以发布事件,“主机”页面将做出反应并翻转页面。

如果您使用任何现有的 MVVM 框架,那当然很好。MVVM Light 有Messenger,Caliburn.Micro 有——你可能已经注意到了—— IEventAggregator

于 2013-05-08T09:32:34.370 回答