我創建了一個自定義控件(繼承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