【问题标题】:Vector Image in WPF Button Template Not Always ShowingWPF 按钮模板中的矢量图像并不总是显示
【发布时间】:2018-10-28 17:00:44
【问题描述】:

我的 WPF 应用程序有几个按钮,上面没有文本,只有一个基于矢量的图像(使用 Path 对象),ControlTemplate 看起来像这样:

<ControlTemplate x:Key="IconButtonContentTemplate" TargetType="{x:Type ButtonBase}">
    <Grid Background="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, Mode=FindAncestor}}">
        <Path HorizontalAlignment="Center" VerticalAlignment="Center" 
            Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, Mode=FindAncestor}}" 
            Height="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, Mode=FindAncestor}}"   
            Data="{Binding (components:ImageButtonAttachedProperties.ImagePathData), RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, Mode=FindAncestor}}"
            Stretch="Uniform" Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, Mode=FindAncestor}}" />
    </Grid>

    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Foreground" Value="LightGray" />
        </Trigger>
        <Trigger Property="IsPressed" Value="True">
            <Setter Property="Foreground" Value="LightGray" />
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Foreground" Value="Gray" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate> 


<Style TargetType="{x:Type Button}" x:Key="ClockButtonStyle" BasedOn="{StaticResource IconButtonStyle}">
    <Setter Property="Template" Value="{StaticResource IconButtonContentTemplate}" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="components:ImageButtonAttachedProperties.ImagePathData" Value="M69.349,65.092C68.714,65.092,68.072,64.925,67.487,64.577L46.294,51.946 46.294,21.239C46.294,19.227 47.925,17.595 49.938,17.595 51.949,17.595 53.581,19.227 53.581,21.239L53.581,47.807 71.217,58.317C72.945,59.348 73.512,61.585 72.483,63.312 71.799,64.457 70.589,65.092 69.349,65.092z M49.938,3.877C24.573,3.877 3.938,24.513 3.938,49.877 3.938,75.241 24.573,95.877 49.938,95.877 75.302,95.877 95.938,75.241 95.938,49.877 95.938,24.513 75.302,3.877 49.938,3.877z M52.876,88.467C52.882,88.395 52.897,88.324 52.897,88.25 52.897,86.615 51.572,85.29 49.937,85.29 48.302,85.29 46.977,86.615 46.977,88.25 46.977,88.324 46.994,88.395 46.999,88.467 27.994,87.032 12.783,71.822 11.349,52.817 11.423,52.822 11.492,52.838 11.567,52.838 13.202,52.838 14.527,51.513 14.527,49.878 14.527,48.243 13.201,46.918 11.567,46.918 11.492,46.918 11.422,46.935 11.349,46.94 12.783,27.933 27.994,12.722 47,11.287 46.995,11.36 46.978,11.43 46.978,11.504 46.978,13.139 48.304,14.464 49.938,14.464 51.572,14.464 52.897,13.138 52.897,11.504 52.897,11.429 52.881,11.36 52.876,11.287 71.882,12.722 87.093,27.932 88.528,46.938 88.455,46.933 88.385,46.916 88.311,46.916 86.676,46.916 85.35,48.242 85.35,49.876 85.35,51.51 86.676,52.836 88.311,52.836 88.385,52.836 88.455,52.82 88.528,52.815 87.094,71.822 71.883,87.032 52.876,88.467z" />
</Style>

我的问题是按钮图像在极少数情况下不显示(99% 的情况下)。仍然可以单击该按钮,但不显示其上的图像。 我不确定是什么原因造成的。矢量图像上的数据绑定?还是填充颜色上的数据绑定?

ImageButtonAttachedProperties.ImagePathDataSystem.Windows.Media.Geometry 对象,它描述了矢量图像。

public static class ImageButtonAttachedProperties
{
    public static readonly DependencyProperty ImagePathDataProperty =
        DependencyProperty.RegisterAttached("ImagePathData", typeof(Geometry), typeof(ImageButtonAttachedProperties), new UIPropertyMetadata(null));

    public static Geometry GetImagePathData(DependencyObject obj)
    {
        return (Geometry)obj.GetValue(ImagePathDataProperty);
    }

    public static void SetImagePathData(DependencyObject obj, Geometry value)
    {
        obj.SetValue(ImagePathDataProperty, value);
    }
}

知道我在这里做错了什么吗?

【问题讨论】:

  • 调试绑定:spin.atomicobject.com/2013/12/11/wpf-data-binding-debug 连接一些可见性/父级更改事件并将它们写入控制台。用位图图像尝试类似的事情。连接到AppDomain.CurrentDomain.FirstChanceException,看看那里是否有可疑之处......并使用可样式化的触发器,当您的用户要求暗模式时,硬编码的颜色看起来很奇怪
  • 使用 Visual Studio Live Tree 或 Snoop 等外部工具检查可视化树。验证所有元素都在您期望的位置,并且所有属性都是您期望的。那么你可能会找到罪魁祸首
  • 根据您的统计,至少有 2 个按钮 in this window 应该会出现问题,但即使经过多次执行,它也不会发生。
  • 无法复现,能否发个有问题的demo项目?此外,如果您可以发布 IconButtonStyle 的代码,这将很有用,因为它可能有一些我不知道的触发器。
  • 尝试显式设置Path 的宽度和高度(没有任何绑定),看看是否会再次发生这种情况?

标签: c# wpf xaml dependency-properties controltemplate


【解决方案1】:

您将模板元素的 desired 维度绑定到模板化父元素的 final 维度;这会产生循环依赖。不要那样做。

模板化控件的大小(例如,您的 Button)取决于其模板内容的所需大小(例如,您的 Path)。如果您使内容的大小取决于模板化父级的大小,那您就是在自找麻烦。

如果我不得不猜测,您可能会陷入布局循环,其中一个布局更新会触发另一个布局更新在下一个滴答时发生。由于布局更新的调度方式,这些并不总是显而易见的(也许通过查看 CPU 使用率除外)。我以前见过这种情况,例如,当“排列”通过使“测量”通过的结果无效时。可见的效果可能相当难以预测:有时事情看起来工作正常,但实际上却没有。

摆脱Path 上的WidthHeight 绑定,并将水平和垂直对齐方式设置为Stretch

【讨论】:

  • Stretch 是 Path 对齐属性的默认值。无需设置。
  • @Clemens 没错,但如果我们真的想要“正确”,Path 上的[H/V]Alignment 属性可能应该绑定到模板化父级的相应[H/V]ContentAlignment 属性。
【解决方案2】:

你应该:

1) 移除填充颜色上的数据绑定以确定是否仍然可以重现问题。

你不能,换个方式试试:

2) 移除 Path 上的数据绑定(使用常量 Path 进行测试)并使用填充颜色上的数据绑定进行测试。

如果 1) 和 2) 无法重现您的问题,请尝试: 3) 在填充颜色和路径上的数据绑定上使用常量值

如果您能够重现 1) 或 2) 中的问题,那么您现在至少知道问题的根源了。 3) 也是如此,但它更复杂,因为 3) 意味着两个数据绑定以某种方式相互影响......

4) 您的问题也可能隐藏在您的主题定义中 - 因此关闭自定义主题并仅使用泛型主题也是一种测试方式,以便了解问题的根源。

5) 我还会尝试在按钮的背景上布置路径,看看这是否能更好地解决您的问题 - 请参阅我在这篇文章中的最后一条评论: Image fill the space on the button in WPF

你确实需要发布一个小的演示应用程序才能获得确定性的答案,否则,仅给出显示的sn-ps恐怕无法说出确切的来源

【讨论】:

    【解决方案3】:

    我不确定是什么原因造成的。

    在某些时候ActualWidthActualHeight(在任何控件上)的值实际上为零,并且这些属性是只读类型的依赖属性。当控件为 LoadedMeasuredArrangedRendered 时会发生这种情况。

    根据FrameworkElement.ActualWidth Property

    因为ActualWidth 是一个计算值,所以您应该知道 可能有多个或增量报告的更改作为 布局系统的各种操作的结果。布局系统 可能正在计算子元素所需的度量空间, 父元素的约束,等等。

    问题是某些东西抖动您的按钮并导致调整大小,而您通过捕捉零值赢得了彩票


    作为一个尝试的过程,我提供了一个关于以两种不同方式容纳矢量图像 Best way to use a vector image in WPF 的答案,我使用的示例在可调整大小的窗口中有 3 个矢量,据我所知它们没有 @987654330 @ 除了重绘。但我将高度/宽度设置为stretch

    也许改变向量的保存方式?

    【讨论】:

    • “捕获零值”意味着在完成布局传递后 ActualWidth 或 ActualHeight 的 final 值将为零,这根本没有意义。尽管如此,宽度和高度绑定是完全多余的。 Grid 已经调整了它的 Path 子节点的大小。 Horizo​​ntalAlignment 和 VerticalAlignment 也是多余的。最后,Background 和 Fill 应该使用 TemplateBindings。
    • Minor nitpick: ActualWidth/Height 依赖属性,但它们是只读没有明确设置的依赖属性(值是从RenderSize 中提取的)。这对于属性受益于 DP 更改通知机制而言意义重大。
    • @MikeStrobel 相应地调整了文本。谢谢
    猜你喜欢
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    • 2013-05-18
    相关资源
    最近更新 更多