对于文本框中的 DataObject.Pasting 事件,我想分配位于视图模型(MVVM 模式)中的 TextBoxPasting 函数。不幸的是,该代码不起作用。我使用图书馆:
xmlns:behaviours =“http://schemas.microsoft.com/xaml/behaviors”。
查看 - 代码:
<TextBox Text="{Binding StartNumber, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" FontSize="16" Height="27" Margin="10"/>
<behaviours:Interaction.Triggers >
<behaviours:EventTrigger EventName="DataObject.Pasting">
<behaviours:InvokeCommandAction x:Name="DataObjectPastingCommand" Command="{Binding DataObjectPastingCommand}" PassEventArgsToCommand="True"/>
</behaviours:EventTrigger>
</behaviours:Interaction.Triggers>
ViewModel - 代码:
public class MechanicViewModel : ViewModelBase, IMechanicViewModel
{
private static readonly Regex _regex = new Regex("[^0-9.-]+");
public MechanicViewModel()
{
DataObjectPastingCommand = new DelegateCommand<DataObjectPastingEventArgs>(TextBoxPasting);
}
public DelegateCommand<DataObjectPastingEventArgs> DataObjectPastingCommand { get; private set; }
private static bool IsTextAllowed(string text)
{
return !_regex.IsMatch(text);
}
private void TextBoxPasting(DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(string)))
{
string text = (string)e.DataObject.GetData(typeof(string));
if (!IsTextAllowed(text))
{
e.CancelCommand();
}
}
else
{
e.CancelCommand();
}
}
}
您的问题明确要求采用符合 MVVM 的方式来处理应用程序视图模型中附加的 UI 事件(或一般 UI 事件)。空无一人。根据定义,视图模型不得参与 UI 逻辑。视图模型没有理由处理 UI 事件。所有事件处理都必须在视图中进行。
虽然在技术上可以在应用程序视图模型中处理 UI 事件,但 MVVM 禁止这样做,并要求此类事件在应用程序视图中处理。如果您想正确实现 MVVM,因为您不想让 UI 渗透到应用程序中,那么您必须在视图中处理此类事件(在 C# 中,又称为代码隐藏,又称为部分类)。
复制和粘贴是纯粹的查看操作:
RoutedEventArgs
对象。RoutedEventArgs
公开源UI元素(通过委托的发送者参数,通过事件参数的Source
和OriginalSource
属性)。RoutedEventArgs
使处理程序能够直接参与 UI 逻辑(例如,通过将事件标记为已处理或取消正在进行的 UI 操作等)。这些都是暗示事件不应该在视图模型中处理。路由事件是与 UI 交互或 UI 行为或渲染逻辑相关的always事件 - 它们由 UI 对象声明和引发。
视图模型不得关心任何 UI 元素,例如他们何时以及如何改变尺寸。
Button.Click
事件是唯一应该触发视图模型操作的事件。此类元素通常实现 ICommandSource
来消除事件订阅。但是,在代码隐藏中处理 Click
事件并将操作从那里委托给视图模型并没有什么问题。
将所有 UI 对象传递到视图模型(通过事件参数)也是明显的 MVVM 违规。
参与 UI 逻辑(复制和粘贴)是另一个 MVVM 违规行为。您必须在控件的代码隐藏中处理
Pasting
事件,或者通过让视图模型类实现 INotifyDataErrorInfo
来实现属性验证。
从用户体验的角度来看,吞没用户操作是“永远”的好主意。
您必须始终提供反馈,以便用户知道他的操作不受支持。如果您无法从一开始就阻止它,例如通过禁用通常由灰色元素可视化的交互,那么您必须提供错误信息来解释为什么不允许该操作以及如何修复它。数据验证是最好的解决方案。
例如,当您在网络应用程序中填写注册表并在输入字段中输入/粘贴无效数据时,您的操作不会被默默吞没。
INotifyDataErrorInfo
的作用完全相同。
并且它不违反 MVVM。 完成任务的推荐 MVVM 方法是实施
INotifyDataErrorInfo
。请参阅
如何添加验证以查看模型属性或如何实现 INotifyDataErrorInfo。 一种不太优雅但仍然有效的 MVVM 解决方案是在视图中实现
DataObject.Pasting
附加事件的事件处理,并从代码隐藏中取消命令。请注意,此解决方案可能违反多项 UI 设计规则。您至少必须向用户提供适当的错误反馈。
对于您的具体情况,您应该考虑实施NumericTextBox
。这也是一个优雅的解决方案,其中输入验证完全由输入字段处理。该控件也可以通过实现绑定验证来使用数据验证,例如定义
ValidationRule
。您将获得一种便捷的方式来向用户显示红色框(可自定义)和错误消息。