码迷,mamicode.com
首页 > Windows程序 > 详细

WPF中关于对前台Xaml中Triggers的一些重要思考。

时间:2018-05-25 01:33:48      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:img   tco   结果   display   font   content   按钮   nta   ide   

原文:WPF中关于对前台Xaml中Triggers的一些重要思考。

    今天在做一个小Demo的时候碰到了一个比较奇怪的问题,就是其中一个Trigger始终无法执行,<Trigger Property="Popup.IsOpen" Value="False">就是当Popup控件关闭的时候不能触发<Setter TargetName="BG" Property="Background" Value="Gray" />这个状态,首先贴一下具体的代码和展现的具体效果。

    <CheckBox x:Name="label" HorizontalAlignment="Center" VerticalAlignment="Center"  FontSize="26" Content="场景列表" HorizontalContentAlignment="Center" 
          VerticalContentAlignment="Center" Opacity="0.6" > <CheckBox.Template> <ControlTemplate TargetType="{x:Type CheckBox}"> <Grid> <Border x:Name="BG" Background="{TemplateBinding Control.Background}"> <ContentPresenter Content="{TemplateBinding ContentControl.Content}"></ContentPresenter> </Border> <Popup x:Name="MyPopup" Placement="Bottom" AllowsTransparency="True" PopupAnimation="Slide" StaysOpen="False"
                    IsOpen="{Binding IsChecked,RelativeSource={RelativeSource TemplatedParent}}" PlacementTarget="{Binding ElementName=BG}"> <StackPanel> <Button Content="按钮1" Width="100" Height="30" FontSize="16" Foreground="Teal"></Button> <Button Content="按钮2" Width="100" Height="30" FontSize="16" Foreground="Teal"></Button> <Button Content="按钮3" Width="100" Height="30" FontSize="16" Foreground="Teal"></Button> <Button Content="按钮4" Width="100" Height="30" FontSize="16" Foreground="Teal"></Button> </StackPanel> </Popup> </Grid> <ControlTemplate.Triggers> <Trigger Property="ToggleButton.IsChecked" Value="True"> <Setter TargetName="BG" Property="Background" Value="Red" /> </Trigger> <Trigger Property="Popup.IsOpen" Value="False"> <Setter TargetName="BG" Property="Background" Value="Gray" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </CheckBox.Template> </CheckBox>

  

  预期的效果是当我们点击该按钮时,弹出Pop并且,设置Border 的背景为红色,但实际情况下是当我们点击之后确实能够弹出Popup但是Border的背景却仍然为灰色。

技术分享图片

     按照我们的理解,当我们点击“场景列表”时,首先执行下面的Trigger,然后设置Border的背景为红颜色。

                  <Trigger Property="ToggleButton.IsChecked" Value="True">                             
                                <Setter TargetName="BG" Property="Background" Value="Red" />                                
                             </Trigger> 

  但是结果是最终的背景色也为灰色,那么删除掉第二个Trigger时,又会有怎样的结果

技术分享图片    也就是说第二个Trigger又将Border的背景设置成灰色了。首先看看第二个Trigger的具体内容:

            <Trigger Property="Popup.IsOpen" Value="False"> 
              <Setter TargetName="BG" Property="Background" Value="Gray" />
            </Trigger>

  

    也就是但是Popup.IsOpen的值为False,但是 IsOpen="{Binding IsChecked,RelativeSource={RelativeSource TemplatedParent}}" IsOpen的值是绑定到CheckBox的               IsChecked属性的,但是IsChecked属性的值为true,这个是怎么回事,也就是说这个Popup.IsChecked属性使用的是默认值,并没有绑定到具体的PopUp控件上,最后我们查找到在进行定义Trigger属性的时候,有一个属性值就是SourceName这个是和TargetName是一对的,即绑定的源头,所以下面做了如下更改:

            <Trigger Property="Popup.IsOpen" Value="False" SourceName="MyPopup">
              <Setter TargetName="BG" Property="Background" Value="Gray" />
            </Trigger>

   这样再运行代码的时候,可以看到效果是可以出来的,也就是Popup.IsOpen属性确实是关联到MyPopup上面,下面就具体截图为证。

技术分享图片

   但是当我们调整两个Trigger的位置的时候,又可以正常执行。 

              <ControlTemplate.Triggers> 
                  <Trigger  Property="Popup.IsOpen" Value="False">
                                <Setter TargetName="BG" Property="Background"  Value="Gray" />
                            </Trigger>                            
                            <Trigger Property="ToggleButton.IsChecked" Value="True">                             
                                <Setter TargetName="BG" Property="Background"   Value="Red" />                                
                            </Trigger> 
                        </ControlTemplate.Triggers>                        

  后来仔细想一下也是对的啊,首先WPF这种查找属性的机制都是基于可视化树向上查找的,当执行这两个Trigger的时候,如果先执行Property="ToggleButton.IsChecked"这个属性的时候,再向下执行第二个Trigger的时候如果没有指定SourceName属性,它会默认沿着视觉树向上查找,由于在CheckBox之上我们是找不到Popup控件的,所以它会使用默认值,所以才有了最开始的问题,所以在我们写Trigger的时候,第一个Trigger里面一定要写视觉树中比较底层的元素,然后一级一级往上写,这样我们就不会出现上面出现的各种莫名其妙的问题。第二种原则就是按照规范的写法为每一个Trigger都写上SourceName属性,这样无论先后顺序都可以执行下去的。这个是在定义Trigger的时候的两条基本原则,在使用时需要特别注意。

 

WPF中关于对前台Xaml中Triggers的一些重要思考。

标签:img   tco   结果   display   font   content   按钮   nta   ide   

原文地址:https://www.cnblogs.com/lonelyxmas/p/9086050.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!