防止按Enter键提交WPF表单

本文关键字:提交 WPF 表单 Enter | 更新日期: 2023-09-27 18:18:32

我有一个WPF XAML屏幕有多个控件(文本框,组合框,按钮等)。背后的代码是用c#编写的。我保留了IsDefault="True"作为其中一个按钮。因此,如果用户在任何文本框中按输入键,则提交表单。

我需要使用提交表单,仅为一个特定的文本框输入键。如果用户在任何其他文本框中按输入键,我不希望提交表单。

我知道我可以使用后面的代码(即*.xaml.cs)实现这一点。但是如何使用MVVM设计模式实现这一点呢?

防止按Enter键提交WPF表单

您可能不关心用户在哪个文本框中按下enter键,您只希望完成整个表单。如果是这种情况,执行验证并使用绑定禁用按钮。

public ICommand SaveCommand
{
    get
    {
        if (_saveCommand == null)
            _saveCommand = new RelayCommand(x => Save(), CanSave);
        return _saveCommand;
    }
}
private void CanSave(object sender)
{
    // Validate properties, ensure viewmodel is in savable state.
    // Maybe you implemented IDataErrorInfo?
    if (Validator.TryValidateObject(this, new ValidationContext(this, null, null), new List<ValidationResult>(), true))
        return true;
    else
        return false;
}
private void Save()
{
    // Database stuff, maybe WCF stuff, etc.
}

可以将按钮的IsDefault属性绑定到允许的TextBox的IsFocused属性,如下所示。

    <TextBox x:Name="TB1" Grid.Row="0" Height="15" Width="300">
    </TextBox>
    <TextBox x:Name="TB2" Grid.Row="1" Height="15" Width="300">
    </TextBox>
    <Button Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Center" Height="40" Width="200" Content="Button"
            IsDefault="{Binding IsFocused, ElementName=TB2}"  Click="Button_Click">
    </Button>

我有它,所以IsEnabled属性被绑定,但它阻止按钮点击工作。然后,我尝试基于TB2或按钮的焦点进行多绑定,但如果TB1被聚焦,仍然会阻止点击,因为禁用的按钮无法接受点击来获取焦点。

在你想处理的文本框上设置AcceptsReturn="True",输入它们自己,而不是路由到表单。

你可以从按钮中删除IsDefault="True",并将命令绑定到文本框本身。在StackOverflow上有很多方法可以做到这一点。我倾向于使用自定义文本框。

public class CommandTextBox : TextBox, ICommandSource
{
    private bool _canExecute;
    private EventHandler _canExecuteChanged;
    protected override bool IsEnabledCore
    {
        get 
        {
            if (Command != null)
                return base.IsEnabledCore && _canExecute;
            return base.IsEnabledCore;
        }
    }
    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandTextBox), new PropertyMetadata(OnCommandChanged));
    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }
    public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(CommandTextBox));
    public object CommandParameter
    {
        get { return GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }
    public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(CommandTextBox));
    public IInputElement CommandTarget
    {
        get { return (IInputElement)GetValue(CommandTargetProperty); }
        set { SetValue(CommandTargetProperty, value); }
    }
    protected override void OnPreviewKeyDown(KeyEventArgs e)
    {
        base.OnPreviewKeyDown(e);
        if (e.Key == Key.Enter)
        {
            if (Command != null)
            {
                RoutedCommand command = Command as RoutedCommand;
                if (command != null)
                    command.Execute(CommandParameter, CommandTarget);
                else
                    Command.Execute(CommandParameter);
            }
            e.Handled = true;
        }
    }
    private void AddCommand(ICommand command)
    {
        var handler = new EventHandler(CanExecuteChanged);
        _canExecuteChanged = handler;
        if (command != null)
            command.CanExecuteChanged += _canExecuteChanged;
    }
    private void CanExecuteChanged(object sender, EventArgs e)
    {
        if (Command != null)
        {
            RoutedCommand command = Command as RoutedCommand;
            // If a RoutedCommand. 
            if (command != null)
                _canExecute = command.CanExecute(CommandParameter, CommandTarget);
            else
                _canExecute = Command.CanExecute(CommandParameter);
        }
        CoerceValue(UIElement.IsEnabledProperty);
    }
    private void HookUpCommand(ICommand oldCommand, ICommand newCommand)
    {
        // If oldCommand is not null, then we need to remove the handlers. 
        if (oldCommand != null)
            RemoveCommand(oldCommand);
        AddCommand(newCommand);
    }
    private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((CommandTextBox)d).HookUpCommand((ICommand)e.OldValue, (ICommand)e.NewValue);
    }
    private void RemoveCommand(ICommand command)
    {
        EventHandler handler = CanExecuteChanged;
        command.CanExecuteChanged -= handler;
    }
}