如何可靠地确定在 WPF 应用程序中是否使用了 ControlTemplate?

6
我该如何可靠地确定以下的ControlTemplate是否在WPF应用程序中使用?文件名为“CheckBoxTemplates.xaml”,并且与主应用程序不在同一程序集中。请注意,当我搜索文件名和资源键时,没有结果。此外,在解决方案中搜索资源键是不可靠的,特别是当有五个资源字典文件包含相同的键时。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:mwt="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Luna">
    <Style x:Key="invertedCheckBox"
           TargetType="CheckBox">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate  TargetType="CheckBox"
...

更多信息

虽然user2250152的答案对于上面的XAML是正确的,但它不能可靠地确定样式是否在使用中。我这么说是因为当我用这种技术来处理另一个样式时,我发现有五个资源字典文件包含相同的键值。因此,我们必须考虑如何可靠地确定哪个样式是使用了定义了重复键的。


在运行时还是编译时? - Patrick Hofman
任意。应用程序中的样式会引起问题。第一步是消除无用的样式。如果有任何方法可以做到这一点,我将不胜感激。即使是一个单独的工具也会有所帮助。 - AMissico
@PatrickHofman; 我不明白。 - AMissico
5个回答

3

ReSharper会展示死代码。虽然其检测算法并非完美,但这是一个良好的起点,允许您跳过任何被它标记为已使用的风格。对于任何被标记为未使用的风格,您可以通过搜索解决方案来检查它是否真的未被使用。


1
这对XAML样式也适用吗?我找不到。 - Patrick Hofman
1
我认为ReSharper不起作用。我故意引发了一个未使用的样式,但它没有给出任何指示。 - AMissico
2
检测算法并不完美,上次使用时,它破坏了正在使用的样式。毋庸置疑,它们永远不会变得完美。至于 OP 的问题,答案是否定的,没有可靠的方法 :-)。这是不可能的,就像 Patrick 所说的那样,当事件发生、触发器发生等等时,样式可以在运行时更改。这是非确定性的。 - Erti-Chris Eelmaa
@Chris:没错,门面类可能是最好的选择。 - Patrick Hofman

2

一种非常规的方法是创建一个附加属性,用于打印使用ControlTemplate的人员。可以这样考虑:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:mwt="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Luna">
    <Style x:Key="invertedCheckBox"
           TargetType="CheckBox">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate  TargetType="CheckBox">
                 <Border my:WhoIsMyDaddy="true" ...>

my:WhoIsMyDaddy 可以作为一个附加属性,当设置为 "true" 时,在初始化时会触发 propertychanged 事件处理程序。一旦处理程序被调用,您将能够访问该附加属性的所有者控件的实例。最后,只需使用该实例打印出任何您想要的内容即可。


有趣。唯一的缺点是你必须要操作每个复选框控件。 - AMissico
我必须转到每个使用 CheckBox 的屏幕,以使用(练习)每个复选框,以查看是否使用了该模板。对吗? - AMissico
不!如果您的所有复选框都使用invertedCheckBox样式,它们将全部初始化附加属性。每个复选框都将拥有自己的布尔类型附加属性。当您在处理程序内设置断点时,您将看到哪个复选框何时将依赖属性附加到自己身上。这就是您将知道控件模板是否正在使用的方法。 - dev hedgehog

2

我能想到几个选项:

  • '开发时间'解决方案:这包括搜索每个文件以查找Style="{StaticResource StyleName}"或类似的内容。这在许多情况下都可以工作,但不是自动化且不太可靠;

  • 运行时解决方案:您可以实例化类库中的每个控件,并迭代其中的每个元素,检查当前分配的Style。这仅适用于立即设置样式,而不是在事件等期间;

  • '代码'解决方案:您可以创建自己的门面静态类,作为获取样式的入口点。请注意,您不再允许使用Style="{StaticResource StyleName}",而是Style="{StaticResource SomeStaticClass.StyleName}"。这仅适用于有质量的开发团队习惯于此工作方法的情况。您可以计算程序运行期间访问样式的次数。如果经过很长时间后仍未使用Style,则可能是要删除的候选项。


有趣。我做了项目#1,但不可靠,因此提出问题。项目#3是一个好主意,但它是否涵盖了样式没有明确设置的情况?对于项目#2,也许Snoop可以做到这一点? - AMissico
我找不到使用 Snoop 的方法。 - AMissico
好的。我对所有的WPF工具不是很熟悉。明天上班时我会看一下。 - Patrick Hofman
抱歉,今天在办公室很忙碌,没有太多时间来研究这个问题。 - Patrick Hofman
没有问题。由于使用了“x:Key”,我可以可靠地删除此控件模板。user2250152的回答和一些实验为这个特定情况提供了可靠的答案。然而,对于在多个文件中定义的其他样式,问题仍然存在。 - AMissico
可以将“附加属性”添加到每个Style中。一旦加载了Style,就会加载此附加属性。这将有助于消除一些隐式加载的样式,如果必要,也可以消除显式加载的样式。 - Erti-Chris Eelmaa

1
你可以使用VisualStudio和“在文件中查找”工具。尝试在整个解决方案中查找样式键,例如invertedCheckBox,以确定样式的使用位置。

我已经做过这个了,但没有找到文件名。我还搜索了“key”。我怎么知道一个 CheckBox 是否使用了这种样式?这就是为什么我发出了这些问题。我需要一种可靠的方法。 - AMissico
在您的解决方案中查找所有 CheckBoxes。检查 CheckBox 是否将样式属性设置为 Style="{StaticResource invertedCheckBox}"。如果什么都没有找到,那么您可以确定该样式未被使用。 - user2250152
我尝试过这样做,但没有发现任何用处。于是我创建了一个测试项目并进行了一些测试。看起来如果定义了 x:Key 但未使用,则该样式不会被使用。因为始终会根据 TargetType 生成一个键,所以不存在隐式使用。 - AMissico
是的。您了解隐式、显式和默认样式吗?<br/> 显式样式 - 直接设置样式属性。在大多数情况下,样式不是内联定义的,而是通过显式键引用为资源。<br/> 隐式样式 - 样式属性未直接设置。但是,该样式存在于资源查找序列(页面、应用程序)的某个级别上,并使用与要应用样式的类型匹配的资源键进行标记。 - user2250152
默认样式 - 也称为主题样式。Style属性不是直接设置的,实际上在运行时之前将读取为空值。在这种情况下,样式来自WPF演示引擎的运行时主题评估。对于不在主题中的隐式样式,类型必须完全匹配 - MyButton Button派生类不会隐式使用Button的样式。 - user2250152
显示剩余2条评论

0

根据您所说的

文件名为“CheckBoxTemplates.xaml”,并且位于与主应用程序不同的程序集中。请注意,当我搜索文件名和资源键时没有结果。

您可以确定此样式未被使用。 据我所知,除了应用程序资源和主题之外,没有任何XAML文件的自动加载。 这意味着任何控件都无法明确或隐式地引用此样式(除非您有一些代码幻术加载XAML文件)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接