Свойства пользовательского элемента управления не изменяются при использовании в шаблоне

Я создал настраиваемый элемент управления (наследует элемент управления), который предоставляет одно перечисленное свойство DependencyProperty. Шаблон элемента управления по умолчанию отображается по-разному в зависимости от выбранного значения свойства с использованием триггеров для включения и выключения элементов. Элемент управления отлично работает, если его поместить непосредственно в UserControl для просмотра в пользовательском интерфейсе. Однако смысл элемента управления состоит в том, чтобы существовать как часть большого составного элемента управления, поэтому он также используется в ControlTemplate другого пользовательского элемента управления. Когда я это делаю, изменения свойства зависимости не распознаются элементом управления. Я проверил это, добавив PropertyChangedCallback в свойство зависимости и установив точку останова, которая никогда не срабатывает.

Например, когда я использую «CustomControl» в таком шаблоне:

<ControlTemplate>
    <my:CustomControl EnumProperty="EnumValue" />
</ControlTemplate>

EnumProperty (которое является DependencyProperty) не изменяется на «EnumValue» и остается значением по умолчанию. И, как я уже сказал, точка останова в PropertyChangedCallback для DP никогда не вызывается.

Что мне не хватает?

ОБНОВЛЕНИЕ

Вот очищенная версия моего элемента управления:

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, а не в ControlTemplate, как я изначально указал).

<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, изменяется передний план CustomControl. Но свойство BorderType не соблюдается — оно всегда отображается со значением по умолчанию BorderType.None.


person SonOfPirate    schedule 26.08.2013    source источник


Ответы (1)


У родителя вашего ControlTemplate должно быть что-то для привязки вашего CustomControl. Затем вы привязываете CustomControl в своем шаблоне к родителю.

В следующем примере я использую Border для шаблона кнопки, которая привязывает свою кисть BorderBrush к фону кнопки:

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

Замените Button на свой «большой составной элемент управления» и Border на my:CustomControl, и вы должны быть установлены...

person Nick    schedule 26.08.2013
comment
Смотрите мое обновление, я считаю, что уже делаю то, что вы предлагаете. Разница в том, что я обнаружил, что мы используем элемент управления в DataTemplate, а не в ControlTemplate (в данном случае). Не знаю, какая разница. - person SonOfPirate; 27.08.2013
comment
Ваш CustomControl привязывается к BorderType TemplatedParent TemplatedParent. Я предполагаю, что ваш передний план изменяется, потому что этот родительский элемент управления имеет свойство переднего плана, которое распространяется на его дочерние элементы. Попробуйте удалить TemplatedParent. в начале вашего пути привязки... - person Nick; 27.08.2013
comment
К сожалению, RelativeSource фактически разрешается в ContentPresenter, таким образом, это второй переход. Когда я удаляю TemplatedParent из начала пути привязки, я получаю следующую ошибку в окне вывода: Ошибка пути BindingExpression: свойство «BorderType» не найдено в «объекте» «ContentPresenter». - person SonOfPirate; 27.08.2013