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的一些重要思考。的更多相关文章
- WPF中动态加载XAML中的控件
原文:WPF中动态加载XAML中的控件 using System; using System.Collections.Generic; using System.Linq; using System. ...
- WPF学习01:初始XAML浅析
本文内容: 浅析WPF应用默认创建的XAML中元素.attributes. 新建WPF工程“HelloWPF”. 初始创建的主窗体XAML代码如下: <Window x:Class=" ...
- 《深入浅出WPF》学习总结之XAML标签语言一
一.XMAL概览 1.XAML在桌面开发及富媒体网络程序的开发中扮演了HTML+CSS+JS的角色. 2.XAML可以将UI和逻辑代码分离,降低耦合度. 3.XAML是一种单纯的申明形语言 4.XAM ...
- 【C#】WPF的xaml中定义的Trigger为什么有时候会不管用,如Border的MouseOver之类的
原文:[C#]WPF的xaml中定义的Trigger为什么有时候会不管用,如Border的MouseOver之类的 初学WPF,知道一些控件可以通过定义Style的Trigger改变要显示的样式,但是 ...
- VS编程,编辑WPF过程中,点击设计器中界面某一控件,在XAML中高亮突出显示相应的控件代码的设置方法。
原文:VS编程,编辑WPF过程中,点击设计器中界面某一控件,在XAML中高亮突出显示相应的控件代码的设置方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net ...
- WPF绑定xaml中绑定对象需用属性表示,字段不可以绑定
在练习WPF绑定时发现对象属性可以在XAML中绑定,但字段是不可以绑定: 比如: private Person person{get;set;} 可以绑定到XAML中,<TextBox Nam ...
- WPF中,怎样将XAML代码加载为相应的对象?
原文:WPF中,怎样将XAML代码加载为相应的对象? 在前面"在WPF中,如何得到任何Object对象的XAML代码?"一文中,我介绍了使用System.Windows.Marku ...
- WPF中CAD control的XAML实现
原文:WPF中CAD control的XAML实现 下面这个XAML文件是cad control里面最重要的一部分,使用Grid包含Viewport,Viewport中包括Camera和mod ...
- WPF中任意Object的XAML代码格式化输出
原文:WPF中任意Object的XAML代码格式化输出 有时候,我们需要将WPF中的控件自身的XAML代码输出成文本,那么,我们可以使用System.Windows.Markup.XamlWriter ...
随机推荐
- 【转】如何修改 video 样式
我们这里说的“修改 video 样式”并不是要自己实现一套 controls,而是尝试修改 video 的默认样式 隐藏全屏按钮 这个很容易查到 video::-webkit-media-contro ...
- foreach 與 reference 的雷
前陣子公司定期技術研討會時,有人提出了一個問題. $arr = [1, 2, 3]; foreach ($arr as &$a) {} foreach ($arr as $a) {} var_ ...
- EL表达式运算符使用
EL表达式关系运算符的使用 == eq 等于 != ne 不等于 > gt 大于 < lt 小于 >= ge 大于等于 <= le 小于等于 举例说明 > 或者 gt, ...
- WiFi-ESP8266入门http(3-1)网页认证上网-post请求(原教程)
教程:http://geek-workshop.com/thread-37484-1-1.html 源码:链接:https://pan.baidu.com/s/1yuYYqsM-WSOb0AbyAT0 ...
- 监控和管理Oracle UNDO表空间的使用
对Oracle数据库UNDO表空间的监控和管理是我们日常最重要的工作之一,UNDO表空间通常都是Oracle自动化管理(通过undo_management初始化参数确定):UNDO表空间是用于存储DM ...
- GDB 命令回顾
0) 为使用 GDB, 编译时需要加入调试信息 -g 选项,例如, $ gcc -g test.c -o test 1) 使用 GDB 开始调试 $ gdb test 也可以, $ gdb $ fil ...
- 输出1-100 , 奇数偶数分别添加标识(for循环语句嵌套if-else语句)
package com.summer.cn; /** * @author Summer * 输出1-100 , 奇数偶数分别添加标识 */ public class Test041518 { publ ...
- 使用python进行utf9编码和解码
在2005年4月1日(也就是愚人节),IEEE的rfc4042文件规定了utf9和utf18这2个所谓的Unicode的高效转换格式. 具体的格式说明,有兴趣的话点击上面的rfc4042链接去观看. ...
- 从统计局采集最新的省市区镇数据,用js在浏览器中运行 V2
本文描述的是对国家统计局于2019-01-31发布的<2018年统计用区划代码和城乡划分代码(截止2018年10月31日)>的采集. 相对于用于和采集2016版.2017版的js代码做了比 ...
- Git超实用总结,再也不怕记忆力不好了
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯工蜂发表于云+社区专栏 Git 是什么? Git 是一个分布式的代码管理容器,本地和远端都保有一份相同的代码. Git 仓库主要是 ...