wpf - ContentPresenter 在触发器调用两次以上后失去数据绑定
问题描述
我创建了一个扩展按钮,其中包含由 XAML 中的触发器调用的 2 种不同边框样式。两者共享相同的 contentpesenter,但在更改边框样式两次以上后,contentpresenter 中的内容无法显示。
下面是整个项目的链接,其中包含一个演示问题的测试床应用程序,我认为问题出在下面的 XAML 中,但我看不出它为什么会中断:
<Style.Resources>
<ContentPresenter x:Key="ButtonContent" Margin="5" HorizontalAlignment="Center"
Content="{Binding Content}"/>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Margin="{Binding KeyMargin}">
<Grid Visibility="{Binding RectangleVisibility}">
<Grid.OpacityMask>
<VisualBrush Visual="{Binding ElementName=rectBorder}" />
</Grid.OpacityMask>
<Border x:Name="rectBorder"
CornerRadius="{Binding BorderCorners}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
BorderThickness="{Binding BorderThickness}"/>
<Viewbox Stretch="Fill"
StretchDirection="Both">
<ContentControl Content="{StaticResource ButtonContent}"/>
</Viewbox>
</Grid>
<Grid Visibility="{Binding EllipseVisibility}">
<Ellipse Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{Binding BorderThickness}"
Fill="{TemplateBinding Background}">
</Ellipse>
<Viewbox Stretch="Fill"
StretchDirection="Both">
<ContentControl Content="{StaticResource ButtonContent}"/>
</Viewbox>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
解决方案
问题很可能是您不能在可视化树中的多个位置拥有相同的元素(在本例中为 ContentPresenter),并且它最终出现的两个网格之一是未定义的,即 WPF 的实现原型.
要复制元素,这可能有效:
<ContentControl Content="{TemplateBinding Content}"/>
或者在你的情况下
<ContentControl Content="{TemplateBinding Content}" Margin="5" HorizontalAlignment="Center"/>
而不是静态资源。<ContentPresenter/>
语法几乎是一个优化的快捷方式(或者您可以在资源上设置 x:Shared="False",但据我所知,将 ContentPresenter 作为静态资源不知道它的用途)
如果 Button 内容本身是一个 UIElement,那么它将在可视化树中直接使用,即两次,这也不起作用。更好的解决方案是在控件模板中只包含一次内容并更改其周围的视觉外观,例如,使用触发器来设置 Grid 的 OpacityMask。
另一个说明是,您的控件模板与 Button 的使用位置非常紧密地绑定,直接绑定到当前数据上下文,这降低了它的可重用性。一些简单的修复方法是使用 TemplateBinding 而不是 Binding 分别用于 BorderThickness Margin(而不是 KeyMargin),因为这些是 Button 的现有属性。
为了获得更好的可重用性和更简洁的代码,您应该考虑创建一个从 Button 派生的自定义控件,该控件具有 BorderCorners 的依赖属性、所需的视觉状态(椭圆与矩形)等。您可能还想使用触发器来获得鼠标悬停效果按钮等。玩得开心控制模板!
推荐阅读
- sql-server - 在 SQL Server 中使用子字符串时的转换问题
- c# - 如何使用代码优先方法实体框架将数据插入关联表
- php - 如何在 github 上推送大型代码库?
- jquery - 如何检查传单弹出窗口是否打开?
- vba - 将单元格的值分配给变量时出现错误 91
- image-processing - 文档图像中的手指检测和移除
- mysql - 根据条件下订单
- java - 执行处理器“org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor”时出错(模板:“索引”-第 93 行,第 69 列)
- reactjs - 我的域在谷歌搜索中显示正在建设中
- flutter - 其他 dart 文件中的颤振访问变量