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 ...
随机推荐
- 在asp.net web api中利用过滤器设置输出缓存
介绍 本文将介绍如何在asp.net web api中利用过滤器属性实现缓存. 实现过程 1,首先在web.config文件下appsettings下定义“CacheEnabled”和“CacheTi ...
- npm run dev 在Linux上持久运行
关于node.js应用程序如何持久运行,我在node.js服务端程序在Linux上持久运行用过. 这次主要是针对是一个vue.js应用程序. vue.js应用程序通常运行命令是npm run dev. ...
- 给大家推荐一个C#下的Ribbon风格的Forms实现示例-含源码
C#下的Ribbon风格的Forms实现示例:源码下载地址
- Golang 爬虫-广度优先(获取html文档中的超链接)
package main import( "fmt" "net/http" "io/ioutil" "regexp" & ...
- SVM-笔记(1)
1 目的 SVM推导是从讨论最优超平面开始的,即为了得到一个能够划分不同超平面的面,即公式1: \begin{equation}w^Tx+b=0 \tag{1} \end{equation} 这个公式 ...
- span<T>之高性能字符串操作实测
.net中的字符串操作性能问题由来已久,幸运的是微软推出了span<T>高性能指针操作封装工具类.这个类到底有多高的性能呢?网上传言反正很高,但是实际上在网上很难找到合适的测试实例,这让本 ...
- 【vue】iView-admin后台管理系统
1.目录手册解析 2.跨域解决(axios访问服务器由于前端地址和后端地址不同源会出现跨域问题) 实例2 3.动态菜单导航+权限 4.webstorm 配置 Eslint 代码检查和自动修复
- Luogu P4323 [JSOI2016]独特的树叶
一道比较好的树Hash的题目,提供一种不一样的Hash方法. 首先无根树的同构判断一般的做法只有树Hash,所以不会的同学可以做了Luogu P5043 [模板]树同构([BJOI2015]树的同构) ...
- 【php增删改查实例】第二十四节 - 文件上传在项目中的具体应用
文件上传在项目中,一般有两个用武之地,分别为设置用户的头像和上传附件.本节我们演示如果进行用户头像的上传. 因为一个用户单独并且唯一对应了一个头像,是一对一的关系,所以我们需要去给tm_users表添 ...
- windows 命令行操作 Mysql 数据库
1 前言 有接手一个新项目,项目中到了 Mysql 数据库 ,这里总结下 windows 命令行操作 Mysql 数据库. 2 Cmd操作数据库 2.1 连接Mysql服务器,命令如下:(root用户 ...