C# 使用xaml在MVVM中有条件地自动单击按钮
我正在编写一个基于MVVM体系结构的应用程序。该应用程序具有类似向导的工作流。在我的应用程序中的几个页面(视图)中,我需要一个按钮,当满足某个条件时,可以自动单击该按钮。使用根向导视图模型将这些视图绑定在一起,该模型有一个ClickNextBtn命令,该命令绑定到根向导视图中的“下一步”按钮。因此,我需要在根向导视图中执行以下操作:C# 使用xaml在MVVM中有条件地自动单击按钮,c#,.net,wpf,xaml,mvvm,C#,.net,Wpf,Xaml,Mvvm,我正在编写一个基于MVVM体系结构的应用程序。该应用程序具有类似向导的工作流。在我的应用程序中的几个页面(视图)中,我需要一个按钮,当满足某个条件时,可以自动单击该按钮。使用根向导视图模型将这些视图绑定在一起,该模型有一个ClickNextBtn命令,该命令绑定到根向导视图中的“下一步”按钮。因此,我需要在根向导视图中执行以下操作: <DataTrigger Binding="{Binding Path=CanAutoClickNext}" Value="True"> <
<DataTrigger Binding="{Binding Path=CanAutoClickNext}" Value="True">
<Setter Property="ClickBtn" Value="true" />
</DataTrigger>
上面示例中的属性没有意义,但希望它能帮助传达我正在尝试做的事情
CanAutoClickNext bool属性在向导视图模型之外可用
在需要自动单击“下一步”按钮的其中一个视图上,我尝试在第一次在根向导视图模型中实例化WizardViewModel时将其作为参数传递给相应视图模型的构造函数,然后在实际加载视图时在其中的方法中调用ClickNextBtn。但这并没有起作用,这并不奇怪
我知道如何以编程方式单击wpf按钮,但要在我拥有的框架中将其全部绑定在一起是一个巨大的挑战。任何反馈都将不胜感激
更新:
我最终重写了UI设计模式(仍然是MVVM),这样现在就不必自动移动到下一个页面,页面内的状态会发生变化,并且一组不同的控件变为活动状态。然后系统会提示用户单击下一步。就像对您的问题所做的评论一样,这应该是
ViewModel
调用单击处理程序的一个问题
如何实现这一点与下面类似
现在在MVVM中,您应该将按钮连接到ViewModel中的ICommand
(如果您使用的是MVVM Light toolkit,它将是RelayCommand
/RelayCommand
)
现在假设虚拟机中的ICommand
变量名为NextButtonCommand
你能做的就是
public bool CanAutoClickNext {
get {
return _canAutoClickNext;
}
private set {
if (value == _canAutoClickNext)
return;
_canAutoClickNext = value;
RaisePropertyChanged(() => CanAutoClickNext);
if (_canAutoClickNext)
NextButtonCommand.Execute(null);
}
}
这样,当VMCanAutoClickNext
中的属性设置为“True”时,ICommand
的执行函数将由VM自动调用。这将所有对VM的逻辑处理分离开来,并使视图保持沉默,正如MVVM在涉及应用程序/业务逻辑时所建议的那样
旁注
如果属性
CanAutoClickNext
没有绑定到视图中的任何内容,那么它似乎是一种浪费。如果是这种情况,我建议去掉该属性,从逻辑合适的位置调用ICommand.Execute(null)
,而不是仅在这种情况下使用INPC属性。我将从另一个角度跟进。假设您已准备好任何消息总线(IEventAggregator
,IMessenger
,无所谓)。我将使用Caliburn.Micro的IEventAggregator
以及命名法,因为这是我最熟悉的。现在您可能有一个非常简单的事件:
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());
}
}
公共类向导主机:IHandle
{
私有只读IEventagor消息总线
公共向导主机(IEventAggregator消息总线)
{
this.messageBus=messageBus;
this.messageBus.Subscribe(this);
}
/这里可能有“real”命令方法,例如:
public void GoToNextQuestion()
{
//做事
}
公共无效句柄(移动下一条消息)
{
GoToNextQuestion();
}
}
公共类向导页
{
私有只读IEventagor消息总线;
私人住宅应搬到下一个;
公共向导页面(IEventAggregator消息总线)
{
this.messageBus=messageBus;
}
公共空间
{
//在某些情况下,您可能希望切换标志或执行您需要/想要执行的任何操作,并且:
如果(应该移动到下一个)
Publish(newmovenext());
}
}
现在,当您在向导页面中DoStuff()
时,您可以发布事件,“主机”页面将做出反应并翻转页面
如果您使用的是任何现有的MVVM框架,那么这当然很好。MVVM Light有
信使
,Caliburn.Micro——正如您可能注意到的那样——IEventAggregator
嗯。。。如果它是MVVM,那么可能最好触发一条消息(聚合事件或您喜欢的任何名称),“宿主”视图模型应该处理该消息。类似于MoveNext
的内容看起来您的视图太“聪明”。在MVVM中,按钮通常绑定到命令。单击按钮将调用命令。为什么不直接在ViewModel中调用命令,而不是尝试实现奇怪的往返过程?@Den根向导视图中需要自动单击的按钮已绑定到根向导视图模型中的命令。用户确实需要手动单击该按钮才能继续。但是在两个视图中,我需要自动单击该按钮。这就是问题所在。@Trustme-I'maDoctor我不确定如何将按钮绑定到视图模型中建议的MoveNext消息处理程序,但我将尝试您的建议。