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控件的顯示方式:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM