Wpf 如何将自定义Controltemplate设置为整个应用程序的默认值?

Wpf 如何将自定义Controltemplate设置为整个应用程序的默认值?,wpf,controltemplate,Wpf,Controltemplate,我决定尝试为菜单和菜单项自定义默认控件模板的许多方面。在Visual Studio中,我选择了我的菜单,在属性面板中找到了“模板”,并选择了“转换为新资源…” 我也为MenuItem做了同样的事。然后,为了测试,我将MenuItem子菜单边框颜色更改为红色。此时,我有一个带有两个ControlTemplates的资源字典和一个如下所示的菜单: <Menu Template="{DynamicResource CustomMenuControlTemplate}"> <M

我决定尝试为菜单和菜单项自定义默认控件模板的许多方面。在Visual Studio中,我选择了我的菜单,在属性面板中找到了“模板”,并选择了“转换为新资源…”

我也为MenuItem做了同样的事。然后,为了测试,我将MenuItem子菜单边框颜色更改为红色。此时,我有一个带有两个ControlTemplates的资源字典和一个如下所示的菜单:

<Menu Template="{DynamicResource CustomMenuControlTemplate}">
    <MenuItem Header="File" Template="{DynamicResource CustomMenuItemControlTemplate}">
        <MenuItem Header="Test 1" />
        <MenuItem Header="Test 2">
            <MenuItem Header="Subtest 1" />
            <MenuItem Header="Subtest 2" />
            <MenuItem Header="Subtest 3" />
        </MenuItem>
        <MenuItem Header="Test 3" />
    </MenuItem>
</Menu>
<ControlTemplate TargetType="MenuItem" ...(other properties)>
<Style BasedOn="{StaticResource {x:Type MenuItem}}" ...(other properties)>
…在我整个应用程序的每个菜单项上

所以,接下来我想我应该有一个适用于所有菜单项的样式,并使用setter设置默认模板:

<Style TargetType="MenuItem">
    <Setter Property="Template" Value="{DynamicResource CustomMenuItemControlTemplate}" />
</Style>

这是可行的(注意所有子菜单上的红色边框),但由于某些原因,它会极大地改变菜单的外观:

在该setter中,我尝试使用DynamicResource和StaticResource绑定,结果相同


所以,我的主要问题是:有没有一种方法可以使用自定义ControlTemplate作为默认值,这样我就不必在每个控件上显式地设置它?第二个问题:为什么使用样式设置模板属性会导致其外观发生如此剧烈的变化?

回答第一个问题:

如果将ControlTemplate放入app.xaml的资源字典中,它将应用于整个应用程序。您的控件模板标题应具有如下内容:

<Menu Template="{DynamicResource CustomMenuControlTemplate}">
    <MenuItem Header="File" Template="{DynamicResource CustomMenuItemControlTemplate}">
        <MenuItem Header="Test 1" />
        <MenuItem Header="Test 2">
            <MenuItem Header="Subtest 1" />
            <MenuItem Header="Subtest 2" />
            <MenuItem Header="Subtest 3" />
        </MenuItem>
        <MenuItem Header="Test 3" />
    </MenuItem>
</Menu>
<ControlTemplate TargetType="MenuItem" ...(other properties)>
<Style BasedOn="{StaticResource {x:Type MenuItem}}" ...(other properties)>

这将使所有MenuItem控件隐式使用该控件模板

<Style TargetType="{x:Type MenuItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                <!-- Insert Control Template Here -->
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

回答第二个问题:

这是因为添加样式会覆盖默认样式,实际上会删除所有内置样式。如果希望样式仅更改一些内容,则样式标记应如下所示:

<Menu Template="{DynamicResource CustomMenuControlTemplate}">
    <MenuItem Header="File" Template="{DynamicResource CustomMenuItemControlTemplate}">
        <MenuItem Header="Test 1" />
        <MenuItem Header="Test 2">
            <MenuItem Header="Subtest 1" />
            <MenuItem Header="Subtest 2" />
            <MenuItem Header="Subtest 3" />
        </MenuItem>
        <MenuItem Header="Test 3" />
    </MenuItem>
</Menu>
<ControlTemplate TargetType="MenuItem" ...(other properties)>
<Style BasedOn="{StaticResource {x:Type MenuItem}}" ...(other properties)>


通过这种方式,它继承了所有常规样式,只需更改您显式定义的样式,这样您就不能在没有键的情况下放置控件模板,并且键不能是WPF中的
{x:Type…}

但是您可以在不使用键的情况下放置
样式
,该样式将是默认样式。-在该样式中,可以设置控件模板

<Style TargetType="{x:Type MenuItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                <!-- Insert Control Template Here -->
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>



这对我来说很有意义,现在。。。特别是关于它是如何覆盖默认样式的。也就是说,我尝试在没有密钥的情况下将控件模板添加到我的app.xaml,但得到的错误与我在资源字典中尝试添加控件模板时的错误相同“每个字典条目必须有一个关联的密钥”。您能准确地解释它应该放在哪里吗?我把它放在app.xaml ResourceDictionary标签中。你仍然可以拥有一个密钥,我在答案中输入的代码只是处理你问题的重要属性。可以随意更改标记中的任何其他属性。如果您想知道为什么有一个标记和一个TargetType,TargetType处理隐式模板,而Key可以用于其他控件类型的显式模板。这有意义吗?我编辑我的代码是为了让你或任何偶然发现它的人更清楚一点谢谢你的编辑。不幸的是,如果不提供密钥,似乎无法将ControlTemplate作为资源。因此,即使设置了TargetType,也不会隐式使用它。使用该键,必须使用该键设置绑定模板属性。此外,您提供的关于BasedOn的解释是有意义的。使用BasedOn,hower,似乎会对布局造成一些更奇怪的影响。在我修改我的问题之前,我会在BasedOn上多读一点。感谢您迄今为止的帮助。您不能将类型作为密钥。这个答案根本没有解决这个问题。