zoukankan      html  css  js  c++  java
  • 【小技巧积累】用Style实现必填提示“*”根据选项的不同而显示或隐藏

    1.问题需求

    有一个界面,界面上有一组单选按钮(一个是“可选”,另一个是“必填”),还有一个“备注”信息的文本输入框。现在要求在选择“必填”时,“备注”信息不能为空,此时应该在“备注”文本框前显示必填标志(常用的是“*”),如图2所示;而在选在“可选”时,“备注”信息可为空,此时必填标志“*”应该隐藏起来,如图1所示。

    图1 备注可选

    图2 备注必填

    2.问题分析

    当然,这个问题实际上很简单。如果是文本“备注”是通过TextBlock和文本输入框放在同一个GroupBox中,那么我们可以在“备注”TextBlock和文本输入框之间加一个显示“*”的TextBlock(为了描述方便,假设将其命名为tbStar)。则在选择“可选”时,将tbStar的Visibility属性设置为Hidden(隐藏);而在选择“必填”时,将tbStar的Visibility属性设置为Visible(可见)。至于,如何响应选择“可选”还是选择“必填”,我们可以使用事件和可以使用命令,这个不是这里要讲的重点,我们下面的代码中用了命令。

    但是,通过图1和图2,我们看到此处的难点是:“备注”和“*”不是显示在GroupBox控件内部的,而是显示在GroupBox的Header属性中的。对于Header属性的设置,我们不可能直接将两个TextBlock控件(一个用于显示“备注”,一个用于显示“*”)设置为其值。于是,我们这里采用样式Style来实现。

    3.实现代码

    关于界面的XAML代码如下所示:

     1 <Window x:Class="WPFTestDemo.MainWindow"
     2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         Title="MainWindow" Height="350" Width="525">
     5     <Window.Resources>
     6         <Style x:Key="setHeaderStyle" TargetType="GroupBox">
     7             <Setter Property="Header">
     8                 <Setter.Value>
     9                     <StackPanel Orientation="Horizontal">
    10                         <TextBlock Text="备注" />
    11                         <TextBlock x:Name="txtStar" Text="*" Foreground="Red" Visibility="Collapsed"/>
    12                     </StackPanel>
    13                 </Setter.Value>
    14             </Setter>
    15         </Style>
    16     </Window.Resources>
    17     <Grid>
    18         <Grid.RowDefinitions>
    19             <RowDefinition Height="*" />
    20             <RowDefinition Height="3*" />
    21         </Grid.RowDefinitions>
    22         <GroupBox Grid.Row="0" Margin="4" >
    23             <StackPanel Orientation="Horizontal">
    24                 <RadioButton VerticalAlignment="Stretch" Content="可选" IsChecked="True"
    25                              Command="{Binding Command}" CommandParameter="NoNeed"/>
    26                 <RadioButton VerticalAlignment="Stretch" Content="必填"
    27                              Command="{Binding Command}" CommandParameter="Need"/>
    28             </StackPanel>
    29         </GroupBox>
    30         <GroupBox Grid.Row="1" Margin="4" Style="{StaticResource setHeaderStyle}">
    31             <TextBox ></TextBox>
    32         </GroupBox>
    33     </Grid>
    34 </Window>

    从上面的代码第30行可见,控件GroupBox引用了静态资源setHeaderStyle。而从第6-15行可见,资源setHeaderStyle通过Setter设置了GroupBox的Header属性为一个StackPanel控件,而在StackPanel中提供了两个TextBlock,一个显示“备注”,一个显示“*”。第24-27行代码显示我们通过命令来响应单选按钮“可选”和“必填”的选择,这里的命令绑定到DataContext的Command属性。下面是界面的视图代码实现,

     1 public partial class MainWindow : Window
     2 {
     3     private ViewModel viewModel = new ViewModel();
     4 
     5     public MainWindow()
     6     {
     7         InitializeComponent();
     8         this.DataContext = this.viewModel;
     9         this.viewModel.Command.ExecuteEvent += new Action<Object>(
    10             delegate(object obj)
    11             {
    12                 OptionEnum oe = OptionEnum.NoNeed;
    13                 Enum.TryParse<OptionEnum>((string)obj, out oe);
    14                 if (oe == OptionEnum.NoNeed)
    15                 {
    16                     TextBlock tb = GetTextBlockStar();
    17                     tb.Visibility = Visibility.Hidden;
    18                 }
    19                 else
    20                 {
    21                     TextBlock tb = GetTextBlockStar();
    22                     tb.Visibility = Visibility.Visible;
    23                 }
    24             });
    25     }
    26     private TextBlock GetTextBlockStar()
    27     {
    28         Style style = (Style)this.FindResource("setHeaderStyle");
    29         Setter sb = (Setter)style.Setters[0];
    30         StackPanel sp = (StackPanel)sb.Value;
    31         return (TextBlock)sp.Children[1];
    32     }
    33 }

    上面代码中的第9-24行的代码就是定义了用于响应单选按钮选择的命令,在第16-17行时,判断出选择了“可选”单选按钮,此时设置显示“*”的TextBlock控件的Visibility属性为Hidden(隐藏);而在第21-22行判断出选择了“必填”单选按钮,此时设置显示“*”的TextBlock控件的Visibility属性为Visible(可见)。而我们如何获取显示“*”的TextBlock控件呢?在辅助方法GetTextBlockStar()中,我们通过Window的FindResource()方法来获取Key为setHeaderStyle的资源,然后再一步步地深入去找到显示“*”的TextBlock控件(这里就不一一说明了)。关于其他的辅助代码如下所示(这些代码就不一一分析)。

     1 public class ViewModel
     2 {
     3     private MyCommand command;
     4     public MyCommand Command
     5     {
     6         get { return command; }
     7         set { command = value; }
     8     }
     9 
    10     public ViewModel()
    11     {
    12         command = new MyCommand();
    13     }
    14 }
    15 
    16 public class MyCommand : ICommand
    17 {
    18     public event Action<Object> ExecuteEvent;
    19 
    20     public bool CanExecute(object parameter)
    21     {
    22         return ExecuteEvent != null;
    23     }
    24 
    25     public void Execute(Object parameter)
    26     {
    27         if (ExecuteEvent != null)
    28         {
    29             ExecuteEvent(parameter);
    30         }
    31     }
    32 
    33     public event EventHandler CanExecuteChanged;
    34 }
    35 
    36 public enum OptionEnum
    37 {
    38     NoNeed,
    39     Need
    40 }
  • 相关阅读:
    day 22 反射,双下方法
    day 21 封装,多态,类的其他属性
    day 20 类与类之间的关系,继承2
    day 19 类的名称空间,组合,派生
    day 18 类,对象
    day 17 re模块
    注意NULL
    SQL_DISTINCT
    重载赋值运算符
    随机序列问题
  • 原文地址:https://www.cnblogs.com/lienhua34/p/2684104.html
Copyright © 2011-2022 走看看