J K*_*ing 2 .net wpf datagrid mvvm mvvm-light
我有一个WPF/MVVM(确切地说是mvvm-light)应用程序,我想识别/捕获datagid的lostfocus事件作为一个整体并将其绑定到视图模型中的ICommand.
问题是,每当数据网格中的控件失去焦点以及数据网格本身失去焦点时,就会触发丢失的焦点事件.在我的应用程序中,如果用户在viewModle"HasErrors"属性为true时尝试"导航"远离当前视图,则会在datagrid lostfocus事件/命令上抛出警告(MVVM类型消息框).结果是,即使用户在数据网格中的控件之间移动,用户也会收到此错误/警告.当数据网格作为一个整体失去焦点时,我只想要它.
是什么让这很难: 简单地说,使用MVVM的原因很难.通常,您可以在lostfocus事件后面的代码中检查FocusManager,以获取当前聚焦的元素,并查看它是否在datagrid中(如此处所述).
是否有针对此问题的MVVM标准解决方案?我不是那么盲目地死硬MVVM从来没有代码落后,我想我只是想知道这是否是那个时代之一或是否有一些策略.我没有考虑过,我很可能.
首先 - 我试图为不同的命令使用不同的命令参数.即:
<DataGrid>
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<cmd:EventToCommand Command="{Binding DataContext.PreNavigateValidateCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
CommandParameter="DataGridLostFocus"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)
以及数据网格中的控件
<DataGrid>
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<cmd:EventToCommand Command="{Binding DataContext.LostFocusValidateCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
CommandParameter="ControlostFocus"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)
注意DataGridLostFocus和ControlLostFocus的命令参数的差异.但是发生的事情是这些命令只发生两次,每个命令参数一次,控制lostfocus首先发生,然后是datadrid lostfocus.
SECOND - 你会注意到不同的命令属性/名称.即使将命令绑定到不同的命令对象也无法解决此问题.将按照与上述相同的顺序调用这两个命令.
第三个数据网格位于网格中,网格位于扩展器内,位于用户控件内.我尝试将ICommand触发器将视觉树绑定到这三个元素.即使放在这三个"父"对象中的任何一个上,丢失的焦点事件也会以相同的方式被触发.
我开始认为我需要找到另一个可以工作的事件,或者完全重新思考我如何处理viewmodels的HasErrors属性的这个错误触发器.
我将非常感谢帮助隔离数据网格的丢失焦点事件,这仍然遵循MVVM标准.
谢谢
我认为我们大多数开发人员(包括我自己)长期以来都误解了MVVM.
这导致无处不在的过度复杂化,因为我们倾向于避免在ALL处进行代码隐藏,而不是真正理解如果我们不在View层中放置任何代码/逻辑,那么就没有绑定,没有转换器,没有RelativeSource,没有XAML在所有.
MVVM的真正精神是separate来自UI的逻辑,而不是避免在视图中有任何代码.
这实际上意味着您可以并且应该Focus通过Code-Behind 解决问题(纯粹是View关注点,btw).但是,这并不意味着您将在Code-Behind中放置任何应用程序/业务逻辑.
简单地说,只需处理代码中的任何UI事件,然后将逻辑委托给ViewModel:
private void DataGrid_LostFocus(object sender, RoutedEventArgs e)
{
if (DataGrid.IsKeyboardFocusWithin) //or whatever UI condition
{
//Resolve the ViewModel via DI, constructor injection or whatever. Then:
ViewModel.DoMyBusinessLogic();
}
}
Run Code Online (Sandbox Code Playgroud)
明白了吗?你不是在这里放置业务逻辑.业务逻辑仍在ViewModel/Model中,而View相关代码(Focus)则放在Code Behind中.
而且,这正是做Commands什么的.他们对View中的某些事件做出反应,然后在ViewModel中调用一些方法,不是吗?
我认为这将真正缓解我们习惯的严格的无代码制策略所带来的痛苦.
我也想听听别人对此的看法
| 归档时间: |
|
| 查看次数: |
1968 次 |
| 最近记录: |