2013-08-26 46 views
0

我创建了一个自定义控件(继承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值呈现。

回答

0

ControlTemplate的父级需要为您的CustomControl绑定一些东西。然后,将模板中的CustomControl绑定到父级。

在下面的例子中,我使用的是边境到模板按钮,结合其BorderBrush到按钮的背景:

<ControlTemplate TargetType="{x:Type Button}"> 
    <Border BorderBrush="{TemplateBinding Background}" /> 
</ControlTemplate> 

与“大复合控件”和边境与我的替换按钮: CustomControl和你应该设置...

+0

看到我的更新,我相信我已经在做你在暗示的。不同之处在于我发现我们在DataTemplate中使用控件,而不是ControlTemplate(在这种情况下)。不知道有什么不同。 – SonOfPirate

+0

您的CustomControl绑定到TemplatedParent的TemplatedParent的BorderType。我在猜测你的前景变化,因为这个父控件有一个Foreground属性传播给它的子项。尝试删除“TemplatedParent”。在绑定路径的开始处... – Nick

+0

不幸的是,RelativeSource实际上会解析为ContentPresenter,因此是第二个“跳跃”。当我从绑定路径的开头删除“TemplatedParent”时,在输出窗口中收到以下错误:BindingExpression路径错误:'Object'上未找到'BorderType'属性ContentPresenter' – SonOfPirate

相关问题