• wpf之Popup弹出自定义输入"键盘"


        在很多工厂的信息化MES系统中,车间的采集数据的机器是触摸屏电脑(工厂环境所限,用外接鼠标键盘反而不方便)。

    由于没有外接键盘,所以用户无法像坐在办公室一样,用鼠标键盘进行录入信息。

    这时我们可以用wpf的Popup控件,当点击一个"文本框"时,弹出一个自定义的键盘(UserControl),实现如下图效果:

    自定义用户控件(UserControl),"键盘":

    Xaml:

    <UserControl x:Class="PopupDemo.NumericKeyboard"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d">
        <UserControl.Resources>
            <Style x:Key="btnNum" TargetType="{x:Type Button}">
                <!--<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>-->
                <!--<Setter Property="Background">
                    <Setter.Value>
                        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                            <GradientStop Color="#F3F3F3" Offset="0"/>
                            <GradientStop Color="#EBEBEB" Offset="0.5"/>
                            <GradientStop Color="#DDDDDD" Offset="0.5"/>
                            <GradientStop Color="#CDCDCD" Offset="1"/>
                        </LinearGradientBrush>
                    </Setter.Value>
                </Setter>-->
                <!--<Setter Property="BorderBrush" Value="#FF707070"/>-->
                <!--<Setter Property="BorderThickness" Value="1"/>-->
                <!--<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>-->
                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>
                <!--<Setter Property="Height" Value="64" />
                <Setter Property="Width" Value="104" />-->
                <!--<Setter Property="Padding" Value="10"/>-->
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Button}">
                            <Border x:Name="border" BorderBrush="#FF474747" BorderThickness="1" CornerRadius="6">
                                <!--<Border.Effect>
                                    <DropShadowEffect BlurRadius="1" ShadowDepth="1" Opacity="0.27"/>
                                </Border.Effect>-->
                                <Border.Background>
                                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                        <GradientStop Color="#FFCCCCCC"/>
                                        <GradientStop Color="WhiteSmoke" Offset="1"/>
                                    </LinearGradientBrush>
                                </Border.Background>
                                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" TextElement.Foreground="#FF565656"  TextElement.FontSize="24" />
                                <!--<TextBlock TextWrapping="Wrap" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="21.333" Foreground="#FF565656"/>-->
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter Property="Background" TargetName="border">
                                        <Setter.Value>
                                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                <GradientStop Color="#FFFF7500"/>
                                                <GradientStop Color="#FFFFC547" Offset="1"/>
                                            </LinearGradientBrush>
                                        </Setter.Value>
                                    </Setter>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style x:Key="btnFunc" TargetType="{x:Type Button}">
                <!--<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
                <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
                <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>-->
                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>
                <!--<Setter Property="Padding" Value="1"/>-->
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Button}">
                            <Border x:Name="border" BorderBrush="#FF565656" BorderThickness="1" CornerRadius="6">
                                <Border.Background>
                                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                        <GradientStop Color="#FFFFC547" Offset="1"/>
                                        <GradientStop Color="#FFF77202"/>
                                    </LinearGradientBrush>
                                </Border.Background>
                                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" TextElement.Foreground="White" TextElement.FontSize="24"/>
                                <!--<TextBlock TextWrapping="Wrap" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" FontSize="21.333"/>-->
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter Property="Background" TargetName="border">
                                        <Setter.Value>
                                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                <GradientStop Color="Gray" Offset="1"/>
                                                <GradientStop Color="#FF2D2D2D" Offset="0"/>
                                            </LinearGradientBrush>
                                        </Setter.Value>
                                    </Setter>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style TargetType="{x:Type ToggleButton}">
                <!--<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
                <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
                <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>-->
                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>
                <!--<Setter Property="Padding" Value="1"/>-->
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ToggleButton}">
                            <Border x:Name="border" BorderBrush="#FF565656" BorderThickness="1" CornerRadius="6">
                                <Border.Background>
                                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                        <GradientStop Color="#FFFFC547" Offset="1"/>
                                        <GradientStop Color="#FFF77202"/>
                                    </LinearGradientBrush>
                                </Border.Background>
                                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" TextElement.Foreground="White" TextElement.FontSize="24"/>
                                <!--<TextBlock TextWrapping="Wrap" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" FontSize="21.333"/>-->
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="False">
                                    <Setter Property="Background" TargetName="border">
                                        <Setter.Value>
                                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                <GradientStop Color="Gray" Offset="1"/>
                                                <GradientStop Color="#FF2D2D2D" Offset="0"/>
                                            </LinearGradientBrush>
                                        </Setter.Value>
                                    </Setter>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </UserControl.Resources>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Button Margin="2" Grid.Column="0" Grid.Row="0" Content="1" x:Name="button1" Click="button1_Click" Style="{StaticResource btnNum}"/>
            <Button Margin="2" Grid.Column="1" Grid.Row="0" Content="2" x:Name="button2" Click="button2_Click" Style="{StaticResource btnNum}"/>
            <Button Margin="2" Grid.Column="2" Grid.Row="0" Content="3" x:Name="button3" Click="button3_Click" Style="{StaticResource btnNum}"/>
            <Button Margin="2" Grid.Column="0" Grid.Row="1" Content="4" x:Name="button4" Click="button4_Click" Style="{StaticResource btnNum}"/>
            <Button Margin="2" Grid.Column="1" Grid.Row="1" Content="5" x:Name="button5" Click="button5_Click" Style="{StaticResource btnNum}"/>
            <Button Margin="2" Grid.Column="2" Grid.Row="1" Content="6" x:Name="button6" Click="button6_Click" Style="{StaticResource btnNum}"/>
            <Button Margin="2" Grid.Column="0" Grid.Row="2" Content="7" x:Name="button7" Click="button7_Click" Style="{StaticResource btnNum}"/>
            <Button Margin="2" Grid.Column="1" Grid.Row="2" Content="8" x:Name="button8" Click="button8_Click" Style="{StaticResource btnNum}"/>
            <Button Margin="2" Grid.Column="2" Grid.Row="2" Content="9" x:Name="button9" Click="button9_Click" Style="{StaticResource btnNum}"/>
            <Button Margin="2" Grid.Column="1" Grid.Row="3" Content="0" x:Name="button0" Click="button0_Click" Style="{StaticResource btnNum}"/>
            <Button Margin="2" Grid.Column="0" Grid.Row="3" Content="清零" x:Name="btnMin" Click="btnMin_Click" Style="{StaticResource btnFunc}" />
            <Button Margin="2" Grid.Column="2" Grid.Row="3" Content="确认" x:Name="btnClose" Click="btnClose_Click"  Style="{StaticResource btnFunc}" />
        </Grid>
    </UserControl>
    View Code

    C#:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    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 PopupDemo
    {
        /// <summary>
        /// NumericKeyboard.xaml 的交互逻辑
        /// </summary>
        public partial class NumericKeyboard : UserControl
        {
            public NumericKeyboard()
            {
                InitializeComponent();
            }
            public bool HasMaxValue
            {
                get { return (bool)GetValue(HasMaxValueProperty); }
                set { SetValue(HasMaxValueProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for HasMaxValue.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty HasMaxValueProperty =
                DependencyProperty.Register("HasMaxValue", typeof(bool), typeof(NumericKeyboard), new UIPropertyMetadata(true));
    
    
    
            public int MaxValue
            {
                get { return (int)GetValue(MaxValueProperty); }
                set { SetValue(MaxValueProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for MaxValue.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty MaxValueProperty =
                DependencyProperty.Register("MaxValue", typeof(int), typeof(NumericKeyboard), new UIPropertyMetadata(0));
    
    
    
            public int Value
            {
                get { return (int)GetValue(ValueProperty); }
                set { SetValue(ValueProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty ValueProperty =
                DependencyProperty.Register("Value", typeof(int), typeof(NumericKeyboard), new UIPropertyMetadata(0));
    
    
    
            public bool IsChecked
            {
                get { return (bool)GetValue(IsCheckedProperty); }
                set { SetValue(IsCheckedProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for IsChecked.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty IsCheckedProperty =
                DependencyProperty.Register("IsChecked", typeof(bool), typeof(NumericKeyboard), new UIPropertyMetadata(false));
    
    
            private void btnMin_Click(object sender, RoutedEventArgs e)
            {
                //if (Item != null && Item.Quantity1 > 0)
                //{
                //    Item.Quantity2 = Item.Quantity1;
                //}
                Value = 0;
            }
    
            private void AddNumber(int num)
            {
                //if (Item != null)
                //{
                //    int cnt = Item.Quantity2 * 10 + num;
                //    if (Item.Quantity1 > 0 && cnt > Item.Quantity1)
                //    {
                //        Item.Quantity2 = Item.Quantity1;
                //    }
                //    else
                //    {
                //        Item.Quantity2 = cnt;
                //    }
                //}
                if (HasMaxValue)
                {
                    Value = Math.Min(MaxValue, Value * 10 + num);
                }
                else
                {
                    Value = Value * 10 + num;
                }
            }
    
    
            private void button2_Click(object sender, RoutedEventArgs e)
            {
                AddNumber(2);
            }
    
            private void button3_Click(object sender, RoutedEventArgs e)
            {
                AddNumber(3);
            }
    
            private void button4_Click(object sender, RoutedEventArgs e)
            {
                AddNumber(4);
            }
    
            private void button5_Click(object sender, RoutedEventArgs e)
            {
                AddNumber(5);
            }
    
            private void button6_Click(object sender, RoutedEventArgs e)
            {
                AddNumber(6);
            }
    
            private void button7_Click(object sender, RoutedEventArgs e)
            {
                AddNumber(7);
            }
    
            private void button8_Click(object sender, RoutedEventArgs e)
            {
                AddNumber(8);
            }
    
            private void button9_Click(object sender, RoutedEventArgs e)
            {
                AddNumber(9);
            }
    
            private void button0_Click(object sender, RoutedEventArgs e)
            {
                AddNumber(0);
            }
    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                AddNumber(1);
            }
    
            private void btnClose_Click(object sender, RoutedEventArgs e)
            {
                IsChecked = false;
            }
    
        }
    }
    View Code

    主窗体:

    Xaml:

    <Window x:Class="PopupDemo.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:PopupDemo"
            Title="MainWindow" Width="700" Height="600" WindowStartupLocation="CenterScreen"  DataContext="{Binding RelativeSource={RelativeSource Self}}">
        <Window.Resources>
            <Style TargetType="{x:Type Button}" x:Key="rightButton">
                <Setter Property="Margin" Value="5" />
                <Setter Property="Padding" Value="10" />
                <!--<Setter Property="FontSize" Value="20" />
                <Setter Property="Foreground" Value="White" />-->
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Button}">
                            <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0" CornerRadius="3,13,3,13" Padding="{TemplateBinding Padding}">
                                <Border.Background>
                                    <SolidColorBrush Color="#FF6C6C6C" />
                                </Border.Background>
                                <ContentPresenter x:Name="content" HorizontalAlignment="Center" VerticalAlignment="Center" TextElement.FontSize="20" TextElement.Foreground="White" />
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter TargetName="border" Property="Background" Value="#FF518CB1" />
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter TargetName="content" Property="TextElement.Foreground" Value="Gray" />
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style x:Key="RadioButtonStyle" TargetType="{x:Type RadioButton}">
                <!--<Setter Property="Margin" Value="5" />-->
                <!--<Setter Property="FontSize" Value="20" />-->
                <!--<Setter Property="Foreground" Value="White" />-->
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type RadioButton}">
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0" CornerRadius="4" Background="Transparent"  Padding="10,2" x:Name="PART_Background">
                                <ContentPresenter x:Name="PART_Content" VerticalAlignment="Center" TextElement.Foreground="Black" />
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="True">
                                    <Setter TargetName="PART_Background" Property="Background">
                                        <Setter.Value>
                                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                <GradientStop Color="#FFFFC547" Offset="1"/>
                                                <GradientStop Color="#FFF77202"/>
                                            </LinearGradientBrush>
                                        </Setter.Value>
                                    </Setter>
                                    <Setter TargetName="PART_Content" Property="TextElement.Foreground" Value="White" />
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Window.Resources>
        <Grid>
            <DockPanel DockPanel.Dock="Right" Margin="0,40,0,0" Width="120" LastChildFill="False">
                <Button x:Name="btnShow" Content="Show" DockPanel.Dock="Top" Margin="0,40,0,0" Click="btnShow_Click"  Style="{StaticResource ResourceKey=rightButton}" />
                <RadioButton x:Name="btnTerminalNo" DockPanel.Dock="Top" Margin="0,40,0,0"  Style="{StaticResource RadioButtonStyle}">
                    <StackPanel Orientation="Vertical">
                        <TextBlock Text="终端编号" FontSize="20" TextAlignment="Center"/>
                        <Popup StaysOpen="False" DockPanel.Dock="Bottom" IsOpen="{Binding Path=IsChecked, RelativeSource={RelativeSource FindAncestor, AncestorType=RadioButton, AncestorLevel=1}}" PopupAnimation="Scroll"  AllowsTransparency="True">
                            <Border Background="White" BorderBrush="Black" BorderThickness="1" Padding="4" Width="360" Height="280">
                                <local:NumericKeyboard HasMaxValue="True" MaxValue="9999" IsChecked="{Binding Path=IsChecked, RelativeSource={RelativeSource FindAncestor, AncestorType=RadioButton, AncestorLevel=1}, Mode=TwoWay}" Value="{Binding Path=TerminalNo, Mode=TwoWay}" />
                            </Border>
                        </Popup>
                        <Border Background="Gray"  CornerRadius="5" BorderBrush="Black" BorderThickness="2" Padding="5" Margin="0,0,0,5" HorizontalAlignment="Stretch">
                            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" FontWeight="Bold" FontSize="32" Text="{Binding Path=TerminalNo}" />
                        </Border>
                    </StackPanel>
                </RadioButton>
            </DockPanel>
        </Grid>
    </Window>
    View Code

    C#:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    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;
    using System.ComponentModel;
    
    namespace PopupDemo
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window,INotifyPropertyChanged
        {
            private int terminalNo;
    
            public int TerminalNo
            {
                get { return terminalNo; }
                set 
                {
                    if(value!=terminalNo)
                    {
                        terminalNo = value;
                        OnPropertyChanged("TerminalNo");
                    }
                }
            }
            
    
            public MainWindow()
            {
                InitializeComponent();
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            public void OnPropertyChanged(string propertyName)
            {
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    
            private void btnShow_Click(object sender, RoutedEventArgs e)
            {
                MessageBox.Show(string.Format("终端编号的值为{0}", TerminalNo));
            }
        }
    }
    View Code

    验证输入后,绑定TextBlock的Text属性上值是否真的变化了:

    总结:

    1.Popup控件永远不会自动显示,为了显示Popup控件必须设置IsOpen属性。

    2.默认情况下,Popup.StaysOen属性被设置为True,并且Popup控件会一直显示,直到显式地将IsOpen属性设置为False;

      如果将Popup.StaysOpen属性设置为False,当用户在其他地方单击鼠标时,Popup效果关闭。

    如果Popup控件的IsOpen属性设置为True时,通过Popup控件的PopupAnimation属性(同时必须要设置属性 AllowsTransparency="True")

    可以设置Popup控件的显示方式:

  • 相关阅读:
    基于fis的前端模块化和工程化方案
    网页中font-family的属性解析
    centos 基础环境配置
    golang的各种数据格式的互相转换
    golang 的编译安装以及supervisord部署
    ip地址库选择
    golang中使用mongodb的操作类以及如何封装
    golang中使用mongodb
    golang使用sqlite
    centos 安装nginx
  • 原文地址:https://www.cnblogs.com/527289276qq/p/5386766.html
Copyright © 2020-2023  润新知