一 引入
项目有个新需求,当点击或触碰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>