我创建了一个自定义控件(继承Control),该控件公开了一个枚举的DependencyProperty。默认控件模板根据属性的选定值使用触发器打开/关闭元素进行不同呈现。该控件在直接放置到用户界面中查看用户控件时效果很好。但是,控件的要点是作为大型组合控件的一部分存在,因此它也可用于另一个自定义控件的ControlTemplate中。当我这样做时,控件无法识别依赖项属性的更改。我通过向依赖属性添加一个PropertyChangedCallback并设置了一个永不被命中的断点来验证这一点。自定义控件的属性在模板中使用时不会改变
例如,当我使用在模板“CustomControl”是这样的:
<ControlTemplate>
<my:CustomControl EnumProperty="EnumValue" />
</ControlTemplate>
的EnumProperty(这是一个DependencyProperty)不改变为“EnumValue”,它仍然是默认值。而且,正如我所说的,DP的PropertyChangedCallback中的断点永远不会被调用。
我错过了什么?
UPDATE
这是我控制的洁净版本:
public class CustomControl : Control
{
static CustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl), new FrameworkPropertyMetadata(typeof(CustomControl)));
}
public StandardIcon()
: base()
{
BorderType = BorderType.None;
}
public static readonly DependencyProperty BorderTypeProperty = DependencyProperty.Register("BorderType", typeof(BorderType), typeof(CustomControl), new PropertyMetadata(BorderType.None));
public BorderType BorderType
{
get { return (BorderType)GetValue(BorderTypeProperty); }
set { SetValue(BorderTypeProperty, value); }
}
}
<Style TargetType="{x:Type local:CustomControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomControl}">
<Border x:Name="Rectangle"
BorderBrush="{TemplateBinding Foreground}"
BorderThickness="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<ContentPresenter ContentSource="Content" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="BorderType" Value="Rectangle">
<Setter Property="BorderThickness" TargetName="Rectangle" Value="2" />
</Trigger>
<Trigger Property="BorderType" Value="RoundedRectangle">
<Setter Property="BorderThickness" TargetName="Rectangle" Value="2" />
<Setter Property="CornerRadius" TargetName="Rectangle" Value="5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
这是它是如何被另一个控制范围内使用(注意,这是在一个DataTemplate,而不是一个控件模板正如我最初指出的那样)。
<Style TargetType="{x:Type local:OtherControl}">
<Setter Property="FontFamily" Value="{x:Static theme:StandardFonts.FontFamily}" />
<Setter Property="FontSize" Value="{x:Static theme:StandardFonts.FontSizeXS}" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<local:CustomControl BorderType="{Binding TemplatedParent.BorderType, RelativeSource={RelativeSource TemplatedParent}}"
Foreground="{Binding TemplatedParent.Foreground, RelativeSource={RelativeSource TemplatedParent}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
然后用它是这样的:
<controls:OtherControl Foreground="Red" BorderType="Rectangle" />
预期前景属性正在发生变化。当我更改OtherControl的Foreground时,CustomControl的Foreground被更改。但BorderType属性没有被尊重 - 它总是使用默认的BorderType.None值呈现。
看到我的更新,我相信我已经在做你在暗示的。不同之处在于我发现我们在DataTemplate中使用控件,而不是ControlTemplate(在这种情况下)。不知道有什么不同。 – SonOfPirate
您的CustomControl绑定到TemplatedParent的TemplatedParent的BorderType。我在猜测你的前景变化,因为这个父控件有一个Foreground属性传播给它的子项。尝试删除“TemplatedParent”。在绑定路径的开始处... – Nick
不幸的是,RelativeSource实际上会解析为ContentPresenter,因此是第二个“跳跃”。当我从绑定路径的开头删除“TemplatedParent”时,在输出窗口中收到以下错误:BindingExpression路径错误:'Object'上未找到'BorderType'属性ContentPresenter' – SonOfPirate