WPF实现自带触控键盘的文本框

一 引入

项目有个新需求,当点击或触碰TextBox时,基于TextBox的相对位置,弹出一个自定义的Keyboard,如下图所示:

WPF实现自带触控键盘的文本框_第1张图片

二 KeyboardControl

先实现一个自定义的KeyboardControl,它继承自Window。

Xaml代码如下:


    
        
            
            
            
        
    

    
        
            
                
            
            
                
                    

后台代码如下:

public partial class KeyboardControl : Window
{
    private int TextIndex { get; set; }
    public string TextStr { get; private set; }//通过该属性,访问Keyboard的文本

    public KeyboardControl(string inputStr)//构造方式传入初始文本
    {
        InitializeComponent();

        TextStr = inputStr;
        tbValue.Text = inputStr;
        tbValue.Focus();
        tbValue.CaretIndex = inputStr.Length;
    }

    public static readonly DependencyProperty CapsProperty = DependencyProperty.Register(
       "Caps", typeof(bool), typeof(KeyboardControl), new PropertyMetadata(default(bool)));
    public bool Caps
    {
        get { return (bool)GetValue(CapsProperty); }
        set { SetValue(CapsProperty, value); }
    }


    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Button button = (Button)sender;
        if (TextIndex == 0)
        {
            tbValue.Text += (string)button.Content;
        }
        else
        {
            tbValue.Text = tbValue.Text.Insert(TextIndex, (string)button.Content);
        }
    }

    private void tbValue_TextChanged(object sender, RoutedEventArgs e)
    {
        TextBox textBox = (TextBox)sender;
        TextIndex = textBox.CaretIndex;
    }

    private void ClearButton_Click(object sender, RoutedEventArgs e)
    {
        tbValue.Text = "";
    }

    private void DELButton_Click(object sender, RoutedEventArgs e)
    {
        if (tbValue.Text.Length > 0)
        {
            if (TextIndex == 0 && tbValue.Text.Length >= 1)
            {
                tbValue.Text = tbValue.Text.Remove(tbValue.Text.Length - 1, 1);
            }
            else if (TextIndex > 0)
            {
                tbValue.Text = tbValue.Text.Remove(TextIndex - 1, 1);
            }
        }
    }

    private void OKButton_Click(object sender, RoutedEventArgs e)
    {
        TextStr = tbValue.Text;
        DialogResult = true;
        Close();
    }

    private void CancelButton_Click(object sender, RoutedEventArgs e)
    {
        DialogResult = false;
        Close();
    }

    private void CapsButton_Click(object sender, RoutedEventArgs e)
    {
        Caps = !Caps;
    }
}

Xaml代码中用到了一个大小写的转换类:

public class CapsConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (parameter == null)
        {
            return "";
        }

        if (value == null)
        {
            return parameter.ToString();
        }

        if (value is bool b)
        {
            return b ? parameter.ToString().ToUpper() : parameter.ToString().ToLower();
        }
        else
        {
            return parameter.ToString();
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

三 TouchTextBox

定义一个TouchTextBox的分部类。

public partial class TouchTextBox
{
    private Control hostControl;

    //OnClick方法调用时,通过Window.ShowDialog方法,打开KeyboardControl
    public void OnClick(object sender, MouseButtonEventArgs e)
    {
        if (sender is TextBox textBox)
        {
            hostControl = textBox;
            //计算KeyboardControl的位置,弹出KeyboardControl
            var text = Show(textBox.Text, textBox);
            //KeyboardControl关闭后,获取其文本值,赋值给TextBox
            if (!string.IsNullOrEmpty(text))
            {
                textBox.Text = text;
            }
            else
            {
                textBox.Text = string.Empty;
            }
        }
    }

    private string Show(string initValue, object sender = null)
    {
        var keyboard = new KeyboardControl(initValue);

        SetPosition(keyboard);

        bool result = keyboard.ShowDialog().Value;
        if (result)
        {
            return keyboard.TextStr;
        }
        else
        {
            return string.Empty;
        }
    }

    private void SetPosition(Window window)
    {
        Point point = hostControl.PointFromScreen(new Point(0.0, 0.0));
        double width = SystemParameters.WorkArea.Width;
        double height = SystemParameters.WorkArea.Height;
        if (-point.Y + hostControl.ActualHeight + 5.0 + window.Height < height)
        {
            window.Top = -point.Y + hostControl.ActualHeight + 5.0;
        }
        else
        {
            window.Top = -point.Y - window.Height - 5.0;
        }
        if (-point.X + window.Width < width)
        {
            window.Left = -point.X;
        }
        else
        {
            window.Left = -point.X - (window.Width - hostControl.ActualWidth);
        }
    }
}

添加一个名为TouchTextBox的资源字典。


    

四 效果展示

在App.Xaml中引入TouchTextBox.Xaml资源。


    
        
            
                
            
        
    

MainWindow界面代码:


    
        
    

设置TextBox的Style为TouchTextBox,则该TextBox实现了自带触控键盘的效果。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

你可能感兴趣的:(WPF实现自带触控键盘的文本框)