【小技巧积累】用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 }

posted on 2012-09-13 22:44  lienhua34  阅读(2576)  评论(0编辑  收藏  举报

导航