假设我想使用事件在视图模型中调用命令。这是不好的做法吗?如果是这样的话?
示例:
代码隐藏
void button1_Click(object sender, MouseEventArgs e)
{
this.ViewModel.OnButton1Click();
}
视图模型
void OnButton1Click()
{
// Do something
}
提前致谢。
答案 0 :(得分:1)
WPF中的MVVM负责处理应用程序的表示逻辑和状态。这意味着视图的代码隐藏文件不应包含任何代码来处理从任何UI引发的事件。 所以你要做的就是打破MVVM
您应该使用以下内容重写代码
<Button Command="{Binding ClickCommand}" Width="100" Height="100" Content="test"/>
窗口背后的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModelBase();
}
}
ViewModel:
public class ViewModelBase
{
public ViewModelBase()
{
_canExecute = true;
}
private ICommand _clickCommand;
public ICommand ClickCommand
{
get
{
return _clickCommand ?? (_clickCommand = new CommandHandler(() => MyAction(), _canExecute));
}
}
private bool _canExecute;
public void MyAction()
{
}
}
public class CommandHandler : ICommand
{
private Action _action;
private bool _canExecute;
public CommandHandler(Action action, bool canExecute)
{
_action = action;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_action();
}
}
答案 1 :(得分:1)
是的,这是不好的做法,因为您直接引用ViewModel
中的View
,这意味着View
和{{1}之间存在依赖关系因而紧密耦合。
该模式明确要求ViewModel
NOT 依赖于特定的View
实例或类型。这里的想法是为多态ViewModel
解耦Views
和ViewModels
(您可以通过多种方式显示相同的数据)。为了使Views
可以重复使用,它不需要具体依赖于特定的View
类型。
更好的方法是使用ViewModel
,如Kamel所说。但是,并非所有事件/交互/控件都必须允许调用Commands
。但是,您可以使用Commands
附带的Commands
程序集将System.Windows.Interactivity.dll
附加到特定事件。
这允许您创建如下所示的XAML:
Blend SDK
..它允许与事件处理程序相同的功能来调用 <i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<i:InvokeCommandAction
Command="{Binding UpdateTextBoxBindingOnEnterCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
,但是以一种解耦的MVVM友好方式。