【问题标题】:Custom control defined in an assembly with ControlTemplates defined in another在程序集中定义的自定义控件与在另一个程序集中定义的 ControlTemplates
【发布时间】:2011-12-07 20:57:44
【问题描述】:

我创建了一个带有自定义控件的库,以简化我同事的一些开发。 然后我创建了一个模板,我想让他们有机会修改默认模板等等。 经过一番研究,我发现了一些关于 Themes、Generic.xaml 和 ThemeInfo 属性的信息,但有些东西不起作用。

所以我最后一次尝试: - AssemblyInfo.cs 中带有 Theme 属性的控件库:

[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //où se trouvent les dictionnaires de ressources spécifiques à un thème
//(utilisé si une ressource est introuvable dans la page, 
// ou dictionnaires de ressources de l'application)
ResourceDictionaryLocation.ExternalAssembly //où se trouve le dictionnaire de ressources générique
//(utilisé si une ressource est introuvable dans la page, 
// dans l'application ou dans l'un des dictionnaires de ressources spécifiques à un thème)

)]

所有控件都继承自 System.Windows.Control 并具有静态构造函数:

DefaultStyleKeyProperty.
         OverrideMetadata(typeof(Tire), new FrameworkPropertyMetadata(typeof(Tire))); 

然后,在引用此库的应用程序中,我有一个包含此类定义的 Themes/Generic.xaml 文件:

<Style TargetType="{x:Type g:Tire}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type g:Tire}">
                <Viewbox Name="view">
                    <Ellipse Stroke="Black" StrokeThickness="10" Width="30" 
                             Height="30"/>
                </Viewbox>
                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding Present}" Value="true">
                        <Setter TargetName="view" Property="Visibility" Value="Visible"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Present}" Value="false">
                        <Setter TargetName="view" Property="Visibility" Value="Collapsed"/>
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我还尝试使用{x:Type g:Tire}ou simplement g:Tire 设置键,但没有成功:在 VS2010 中,控件在没有控件模板的情况下呈现。

为了成功显示控件,我必须将 generic.xaml 文件作为 ResourceDictionary 添加到 app.xaml 中,而我在第二个程序集中添加或不添加 ThemeInfo 属性。

另一个相关问题:如果在 window.xaml 文件或另一个控件 xaml 文件中,为了使用样式的强大功能,我添加:

<Style TargetType="{x:Type g:Tire}">
    <Setter Property="Width" Value="20"/>
</Style>

系统似乎覆盖了 generic.xaml 中定义的样式,并且不再呈现控件模板。为了检查,我查看了属性网格中的 Template 属性,当在同一程序集中定义自定义控件时,值的来源被引用为“Defined in Style”而不是经典的“Inheritance”。

所以我的问题,有人可以指出我应该在哪里克服这种情况或帮助我找到准备这种设置的正确方法:在类库中定义控件,并使用默认样式机制定义控件wpf 应用程序中 generic.xaml 文件中的模板?

提前致谢!

更新:

我看了一些东西,而且更清楚了:因为我不打算以一般方式使用主题,所以我必须以某种方式设置样式系统以使用在客户库作为“通用”字典。

通过在源程序集中添加 ThemeInfo(...None, ...None) 并将客户 xaml 文件作为资源添加到客户程序集中,我设法将 DependencyPropertyHelper.GetValueSource(customControl1, Library.CustomControl.TemplateProperty).BaseValueSource 返回的值从 Style 更改为Default,但如果在应用程序中定义了样式,模板仍然会被覆盖:

<Window x:Class="WpfApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:Library;assembly=Library">
<Grid>
    <Grid.Resources>
        <Style TargetType="my:CustomControl"></Style>
    </Grid.Resources>
    <my:CustomControl HorizontalAlignment="Left" Margin="128,95,0,0" Name="customControl1" VerticalAlignment="Top" Height="157" Width="253" />
</Grid>

而且,在属性网格中,Template属性的来源依然设置为Style...

我想我现在正在寻找一种将样式设置为隐式或默认样式的方法。(在客户程序集中为源程序集中定义的控件定义的那个)。

【问题讨论】:

  • 为了清楚起见,我现在在 WpfApp 客户应用程序中使用库类库中定义的简单 CustomControl 来简化解释并找到解决方案。

标签: wpf styles custom-controls controltemplate


【解决方案1】:

我并不完全清楚哪个部分不工作以及您想为您的同事提供什么模板来修改默认外观,但这就是您需要使用 WPF 中的自定义控件执行的操作:

创建一个继承自的自定义控件类

System.Windows.Controls.Control

您正确获取了构造函数部分,因此下一步是在与您的自定义控件相同的项目中创建一个名为“Themes”的文件夹,并在其中添加 Generic.xaml。这就是 WPF 将在其中查找默认控件模板的位置。

定义实现目标类型的样式:

<Style TargetType="{x:Type local:Tire}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:Tire}">
                <!--  there goes your template: grids / stackpanels, etc -->

对于您想要使用控件的每个项目,您都有机会重新定义样式:

<Style TargetType="{x:Type custom:Tire}">
    <Setter Property="Width" Value="150"/>
    <!-- any customer dependency property can be set here as well-->

如果您希望这些属性真正改变,您需要在源程序集中使用 TemplatedParent 来绑定这些属性,而不是对它们进行硬编码。

【讨论】:

  • 感谢您的支持,但我在这里寻找的是在客户程序集中以隐式方式定义此默认样式。这样,如果一个人想在同一个应用程序中定义一个显式样式(而不是实际定义控件的程序集),它可以这样做而无需添加“基于”指令并保持模板定义(不在源大会)。
  • 对,只要您在 generic.xaml 的源程序集中定义了样式,它就会应用于客户程序集。如果客户想要覆盖默认样式,他们总是可以这样做。最后一个 xaml 示例显示了这一点。
  • 是的,但是如果我不想在源程序集中定义任何样式,可以在客户程序集中以隐式方式将其定义为默认样式,以便我们可以在同一个程序集中添加一个显式样式不覆盖所有样式(例如设置边距或大小..)?
  • 根据我的经验,每当您创建样式时,它只会覆盖您特别想要覆盖的那些属性。在这一点上,您在源程序集中或客户端程序集中拥有样式(您提到的隐式样式)没有区别。它的效果相同,除了从 WPF 的角度来看,您必须在 generic.xaml 的源程序集中有一个样式。我建议你尝试一下,你会看到它自己。
  • 其实我已经试过了:)。在我的问题的更新中,您可以在 Grid 资源中看到一个空样式,因此它不应覆盖任何内容。包含 ControlTemplate 的样式在作为 ResourceDictionary 添加到 app.xaml 的 xaml 文件中定义。不幸的是,如果我让空样式,我的控件就会消失(除非我添加了我不想添加的 basedon 属性)......我会在网上放一些资源来更好地解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多