在 WPF 中,是否可以在 UserControl 本身内为 UserControl 定义一个 ControlTemplate(无需在 VS 中获取 warnings/errors)?

In WPF is it possible to define a ControlTemplate for a UserControl inside the UserControl itself (without getting warnings/errors in VS)?

我有一个 UserControl,我想在 window 的某些部分显示不同的控件模板。但我想将这些模板放在 UserControl 本身中(以便更好地维护)。这是:

<UserControl x:Class="PruebasDeWPF.MyUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:PruebasDeWPF"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
    <ControlTemplate x:Key="UserControlTemplate1" TargetType="local:MyUserControl">
        <Grid>
            <Rectangle Fill="Red"></Rectangle>
        </Grid>
    </ControlTemplate>
    <ControlTemplate x:Key="UserControlTemplate2" TargetType="local:MyUserControl">
        <Grid>
            <Rectangle Fill="Blue"></Rectangle>
        </Grid>
    </ControlTemplate>
</UserControl.Resources>
<Grid>

</Grid>

现在用的时候:

<Window x:Class="PruebasDeWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PruebasDeWPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <local:MyUserControl Template="{StaticResource UserControlTemplate1}"></local:MyUserControl>
    </Grid>
</Window>

我在 Visual Studio 中收到一条错误消息,提示无法找到资源且控件未显示。如果我将模板更改为 DynamicResource,我会收到与警告相同的消息,但控件会显示。无论如何,程序运行良好。那么,如何将 UserControl 及其模板放在一起而不会产生这些烦人的问题 warnings/errors?我需要一个特定的 ResourceDictionary(另一个文件)吗?

您尝试执行的操作不适用于 UserControl。

尝试查找有关创建自定义控件的文章。

基本上,您创建一个新的 class(只是一个 class),继承自 ContentControl,并使用名为 "ContentTemplate" 的 属性,就像您使用 "Template" 属性,在您提供的代码示例中。

如果您要在控件中应用任何特定逻辑,请重写 OnApplyTemplate 方法

如果您将模板存储在控件中,那么我认为您不能将它用作 StaticResource。参见:https://msdn.microsoft.com/en-us/library/hh758287.aspx

Attempting to specify a StaticResource to a key that cannot resolve throws a XAML parse exception at run time.

加载时您的控件不存在,因此模板不存在,因此对模板不存在的键的引用失败。

DynamicResources 仅在 运行 时解析,这就是为什么您的程序 运行s 但带有警告。设计器中的警告是“我现在找不到这个,但当程序 运行 时也许可以找到”。

您尝试使用的模式并不真正适合资源,因为它们的加载方式是:作为自上而下的树。要在内部定义的选项之间切换,在 UserControl 上定义 属性 更合适(DependencyProperty 如果你想绑定它),它可以指示应该使用哪个可用模板用过的。这可以是字符串、数字或(可能是最好的选项)列出可用选项的 enum。在您的 UserControl 中,您可以根据该值切换使用的内部定义模板。此基本方法用于各种框架控件 - 例如 Slider.Orientation.