Bootstrap

35.文本框回车下发 C#例子 WPF例子

就是一个简单的回车触发事件的例子。在该例子中按下回车消息框会返回文本框输入的内容

C#代码:

using System.Printing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace practice
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void TextBox_TextChanged(object sender, KeyEventArgs e)
        {
            if(e.Key == Key.Enter)
            {
                MessageBox.Show($"{textbox.Text}");
            }
        }
        //Key Event Arguments键盘事件参数

    }



    
}

Extensible Application Markup Langguage:

<Window x:Class="practice.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:practice"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid Margin="100">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBox x:Name="textbox" KeyDown="TextBox_TextChanged" FontSize="87"/>
    </Grid>
</Window>



如果想在MVVM中也使用Enter下发,会有亿点点复杂。

在MVVM架构中,为TextBox实现回车下发机制(即在用户按下回车键时执行某些操作)确实需要一些额外的考虑,因为MVVM强调视图(View)和视图模型(ViewModel)之间的分离。不过,这并不意味着必须采用非常复杂的方法,如事件聚合器,或者接受潜在的风险来使用控件自带的事件。

以下是在MVVM架构中实现TextBox回车下发机制的方法,同时保持视图和视图模型之间的分离:

使用附加行为(Attached Behavior)
附加行为是一种将特定功能附加到WPF控件上的技术,而不需要修改控件本身的代码。您可以创建一个附加行为来处理TextBox的KeyDown事件,并在其中检查是否按下了回车键。如果是,则调用视图模型上的某个方法。这样,您可以将事件处理逻辑与视图模型分离,同时仍然能够在XAML中声明性地应用它。

        <TextBox Grid.Row="1" Grid.Column="2" Height="50" Width="200"      Text="{Binding TextBoxText3, UpdateSourceTrigger=Explicit}"
local:TextBoxEnterBehavior.EnterCommand="{Binding UpdateTextCommand}" />

前台的TextBox绑定一个附加行为,目标是实现enter下发。这里的数据绑定更新触发方式为Explicit,就是只有通过显式赋值才可以触发。不会像前两个框图里的实时改变,失焦改变。

后台一个是要定义附加行为相关代码。一个是要定义事件。一个还要绑定属性。

代码:

XAML:

<Window x:Class="回车下发.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:回车下发"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid Margin="30">



        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Row="0" Grid.Column="0" Height="50" Width="200" Background="#FFEEEEEE" Text="{Binding TextBoxText1}"/>
        <TextBlock Grid.Row="0" Grid.Column="1" Height="50" Width="200" Background="#FFEEEEEE" Text="{Binding TextBoxText2}"/>
        <TextBlock Grid.Row="0" Grid.Column="2" Height="50" Width="200" Background="#FFEEEEEE" Text="{Binding TextBoxText3}"/>

        <TextBox Grid.Row="1" Grid.Column="0" Height="50" Width="200" Text="{Binding TextBoxText1,UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox Grid.Row="1" Grid.Column="1" Height="50" Width="200" Text="{Binding TextBoxText2,UpdateSourceTrigger=Default}"/>
        <TextBox Grid.Row="1" Grid.Column="2" Height="50" Width="200"      Text="{Binding TextBoxText3, UpdateSourceTrigger=Explicit}"
local:TextBoxEnterBehavior.EnterCommand="{Binding UpdateTextCommand}"/>



    </Grid>
</Window>

后台:

using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace 回车下发
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext=new ViewModel();
        }
    }
}

文件一:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows;

namespace 回车下发
{
    // AttachedBehavior.cs
    public static class TextBoxEnterBehavior
    {
        // 定义一个依赖属性来存储要执行的命令
        public static readonly DependencyProperty EnterCommandProperty =
            DependencyProperty.RegisterAttached(
                "EnterCommand",
                typeof(ICommand),
                typeof(TextBoxEnterBehavior),
                new PropertyMetadata(null, OnEnterCommandChanged));

        // 获取依赖属性的值
        public static ICommand GetEnterCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(EnterCommandProperty);
        }

        // 设置依赖属性的值
        public static void SetEnterCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(EnterCommandProperty, value);
        }

        // 当EnterCommand属性改变时的回调
        private static void OnEnterCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TextBox textBox = d as TextBox;
            if (textBox != null)
            {
                textBox.KeyDown -= TextBox_KeyDown;
                ICommand command = (ICommand)e.NewValue;
                if (command != null)
                {
                    textBox.KeyDown += TextBox_KeyDown;
                }
            }
        }

        // 处理TextBox的KeyDown事件
        private static void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Return)
            {
                TextBox textBox = sender as TextBox;
                if (textBox != null)
                {
                    ICommand command = GetEnterCommand(textBox);
                    if (command != null && command.CanExecute(textBox.Text))
                    {
                        command.Execute(textBox.Text);
                    }
                }
            }
        }
    }
}

ViewModel:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace 回车下发
{
    class ViewModel:BindableBase
    {
        private string _textBoxText1="实时改变";
        public string TextBoxText1 
        {
            get { return _textBoxText1; }
            set 
            { 
                SetProperty(ref _textBoxText1, value);
            }
        }

        private string _textBoxText2 = "失焦改变";
        public string TextBoxText2
        {
            get { return _textBoxText2; }
            set
            {
                SetProperty(ref _textBoxText2, value);
            }
        }
        private string _textBoxText3 = "enter改变";
        public string TextBoxText3
        {
            get { return _textBoxText3; }
            set
            {
                SetProperty(ref _textBoxText3, value);
            }
        }



        //定义命令,绑定命令,被执行的命令
        public ICommand UpdateTextCommand { get; private set; }

        public ViewModel()
        {
            UpdateTextCommand = new DelegateCommand<string>(param => UpdateText(param));
        }
        //命令执行内容
        private void UpdateText(string text)
        {
            //就是在这里更新属性的
            TextBoxText3=text;
            System.Diagnostics.Debug.WriteLine("Text updated: " + text);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

;