网站首页 编程语言 正文
一 引入
项目有个新需求,当点击或触碰TextBox时,基于TextBox的相对位置,弹出一个自定义的Keyboard,如下图所示:
二 KeyboardControl
先实现一个自定义的KeyboardControl,它继承自Window。
Xaml代码如下:
<Window x:Class="WpfApp1.KeyboardControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApp1" AllowsTransparency="True" WindowStyle="None" ResizeMode="NoResize" Background="Transparent" Height="290" Width="668"> <FrameworkElement.Resources> <ResourceDictionary> <Style TargetType="{x:Type Button}" x:Key="btnNum"> <Setter Property="Width" Value="50"/> <Setter Property="Height" Value="50"/> <Setter Property="Margin" Value="0 0 5 5"/> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="Cursor" Value="Hand"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Border Name="border" BorderBrush="#FF474747" BorderThickness="1" CornerRadius="6"> <Border.Background> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FFCCCCCC" /> <GradientStop Color="WhiteSmoke" Offset="0.5" /> <GradientStop Color="#FFCCCCCC" Offset="1" /> </LinearGradientBrush> </Border.Background> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" TextElement.Foreground="#333333" TextElement.FontSize="18" /> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="{x:Type Button}" x:Key="btnFunc"> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="Width" Value="50"/> <Setter Property="Height" Value="50"/> <Setter Property="Margin" Value="0 0 5 5"/> <Setter Property="Foreground" Value="#333333"/> <Setter Property="Cursor" Value="Hand"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Border Name="border" BorderBrush="#FF565656" BorderThickness="1" CornerRadius="6" Background="Orange"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" TextElement.Foreground="White" TextElement.FontSize="18" /> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <local:CapsConverter x:Key="CapsConverter"/> </ResourceDictionary> </FrameworkElement.Resources> <Border Background="Gray" CornerRadius="6" BorderThickness="1" BorderBrush="#333333"> <StackPanel Margin="5 10 5 5" > <Grid> <TextBox Name="tbValue" FontSize="28" Height="40" Background="Transparent" BorderBrush="Silver" BorderThickness="1" Foreground="White" HorizontalContentAlignment="Right" SelectionChanged="tbValue_TextChanged" TextChanged="tbValue_TextChanged" /> </Grid> <WrapPanel Orientation="Vertical" > <WrapPanel Margin="0 10 0 0"> <Button Content="1" Click="Button_Click" Style="{StaticResource btnNum}" /> <Button Content="2" Click="Button_Click" Style="{StaticResource btnNum}" /> <Button Content="3" Click="Button_Click" Style="{StaticResource btnNum}" /> <Button Content="4" Click="Button_Click" Style="{StaticResource btnNum}" /> <Button Content="5" Click="Button_Click" Style="{StaticResource btnNum}" /> <Button Content="6" Click="Button_Click" Style="{StaticResource btnNum}" /> <Button Content="7" Click="Button_Click" Style="{StaticResource btnNum}" /> <Button Content="8" Click="Button_Click" Style="{StaticResource btnNum}" /> <Button Content="9" Click="Button_Click" Style="{StaticResource btnNum}" /> <Button Content="0" Click="Button_Click" Style="{StaticResource btnNum}" /> <Button Content="-" Click="Button_Click" Style="{StaticResource btnNum}" /> <Button Content="Del" Click="DELButton_Click" Style="{StaticResource btnFunc}" Margin="0 0 0 5"/> </WrapPanel> <WrapPanel Margin="25 0 0 0"> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=q}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=w}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=e}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=r}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=t}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=y}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=u}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=i}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=o}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=p}" Click="Button_Click"/> <Button Content="Clear" Click="ClearButton_Click" Style="{StaticResource btnFunc}" /> </WrapPanel> <WrapPanel Margin="45 0 0 0"> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=a}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=s}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=d}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=f}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=g}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=h}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=j}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=k}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=l}" Click="Button_Click"/> <Button Content="." Click="Button_Click" Style="{StaticResource btnNum}" /> </WrapPanel> <WrapPanel Margin="70 0 0 0"> <Button Content="A/a" Click="CapsButton_Click" Style="{StaticResource btnFunc}" /> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=z}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=x}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=c}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=v}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=b}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=n}" Click="Button_Click"/> <Button Style="{StaticResource btnNum}" Content="{Binding Path=Caps,RelativeSource={RelativeSource AncestorType={x:Type local:KeyboardControl}},Converter={StaticResource CapsConverter},ConverterParameter=m}" Click="Button_Click"/> <Button Content="Cancel" Click="CancelButton_Click" IsCancel="True" Style="{StaticResource btnFunc}" Width="70" /> <Button Content="OK" Click="OKButton_Click" IsDefault="True" Style="{StaticResource btnFunc}" Width="70" Margin="0 0 0 5"/> </WrapPanel> </WrapPanel> </StackPanel> </Border> </Window>
后台代码如下:
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的资源字典。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="WpfApp1.TouchTextBox"> <Style x:Key="TouchTextBox" TargetType="{x:Type TextBox}"> <EventSetter Event="PreviewMouseLeftButtonDown" Handler="OnClick" /> </Style> </ResourceDictionary>
四 效果展示
在App.Xaml中引入TouchTextBox.Xaml资源。
<Application x:Class="WpfApp1.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApp1" StartupUri="MainWindow.xaml"> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/WpfApp1;component/TouchTextBox.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application>
MainWindow界面代码:
<Window x:Class="WpfApp1.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" mc:Ignorable="d" Title="MainWindow" Height="800" Width="1200"> <StackPanel> <TextBox Text="Pop up the keyboard after touching" Width="400" HorizontalAlignment="Left" FontSize="18" Margin="20,20" Style="{StaticResource TouchTextBox}"/> </StackPanel> </Window>
设置TextBox的Style为TouchTextBox,则该TextBox实现了自带触控键盘的效果。
原文链接:https://www.cnblogs.com/wwwen/p/16747668.html
相关推荐
- 2022-03-20 android Retrofit2网络请求封装介绍_Android
- 2022-06-24 深度解析Python线程和进程_python
- 2022-08-17 Python pandas.replace的用法详解_python
- 2023-06-18 C#使用udp如何实现消息的接收和发送_C#教程
- 2021-12-03 关于Redis数据库入门详细介绍_Redis
- 2022-04-09 MyBatis 查询返回数据类型Map,空字段数据不返回
- 2022-08-07 pandas时间序列之pd.to_datetime()的实现_python
- 2022-07-06 如何使用Python OpenCV提取物体轮廓详解_python
- 最近更新
-
- window11 系统安装 yarn
- 超详细win安装深度学习环境2025年最新版(
- Linux 中运行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存储小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基础操作-- 运算符,流程控制 Flo
- 1. Int 和Integer 的区别,Jav
- spring @retryable不生效的一种
- Spring Security之认证信息的处理
- Spring Security之认证过滤器
- Spring Security概述快速入门
- Spring Security之配置体系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置权
- redisson分布式锁中waittime的设
- maven:解决release错误:Artif
- restTemplate使用总结
- Spring Security之安全异常处理
- MybatisPlus优雅实现加密?
- Spring ioc容器与Bean的生命周期。
- 【探索SpringCloud】服务发现-Nac
- Spring Security之基于HttpR
- Redis 底层数据结构-简单动态字符串(SD
- arthas操作spring被代理目标对象命令
- Spring中的单例模式应用详解
- 聊聊消息队列,发送消息的4种方式
- bootspring第三方资源配置管理
- GIT同步修改后的远程分支