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

简介: 原文:WPF中关于对前台Xaml中Triggers的一些重要思考。    今天在做一个小Demo的时候碰到了一个比较奇怪的问题,就是其中一个Trigger始终无法执行,就是当Popup控件关闭的时候不能触发这个状态,首先贴一下具体的代码和展现的具体效果。
原文: 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的时候的两条基本原则,在使用时需要特别注意。

 

目录
相关文章
|
5月前
|
XML 开发框架 .NET
|
C# 前端开发
WPF中Style文件的引用——使用xaml代码或者C#代码动态加载
原文:WPF中Style文件的引用——使用xaml代码或者C#代码动态加载   WPF中控件拥有很多依赖属性(Dependency Property),我们可以通过编写自定义Style文件来控制控件的外观和行为,如同CSS代码一般。
4539 0
|
7月前
|
IDE C# 开发工具
2000条你应知的WPF小姿势 基础篇<40-44 启动关闭,Xaml,逻辑树>
2000条你应知的WPF小姿势 基础篇<40-44 启动关闭,Xaml,逻辑树>
33 0
|
9月前
|
C#
WPF技术之Xaml Window
WPF Window 是一个 WPF 窗口类,它具有许多属性枚举可以控制窗口的外观和行为。
81 0
WPF技术之Xaml Window
|
9月前
|
XML 数据格式 C++
WPF-疑难问题-xaml编码导致中文字符编译无效
WPF-疑难问题-xaml编码导致中文字符编译无效
113 0
|
12月前
|
C#
4.使用代码和未经编译的XAML创建WPF应用程序
4.使用代码和未经编译的XAML创建WPF应用程序
59 0
|
数据采集 人工智能 监控
【WPF】CAD工程图纸转WPF可直接使用的xaml代码技巧
随着工业化的进一步发展,制造业、工业自动化等多领域,都可能用到上位监控系统。而WPF在上位监控系统方面,应该算是当下最流行的前端框架之一了。而随着监控体系的不断完善与更新迭代,监控画面会变得越来越复杂、多样化和全面化。
246 0
【WPF】CAD工程图纸转WPF可直接使用的xaml代码技巧
|
C# 数据格式 XML
WPF XAML 特殊字符(小于号、大于号、引号、&符号)
原文:WPF XAML 特殊字符(小于号、大于号、引号、&符号)     XAML 受限于 XML 规则。例如, XML 特别关注一些特殊字符,如  & < > 如果试图使用这些字符设置一个元素内容,将会遇到许多麻烦,因为 XAML 解析器认为您正在做其他的事情——例如,创建一个嵌套元素。
1833 0
|
XML C# 数据格式
XAML属性赋值转换之谜(WPF XAML语法解密)
原文:XAML属性赋值转换之谜(WPF XAML语法解密) XAML与XML类似,就是XML延伸过来的。为了更好的表达一些功能,WPF对XML做了扩展,有些功能是WPF在后台悄悄的替你做了。有时候,虽然实现了某个功能,但是对实现原理还是很茫然。
931 0