Silverlight Custom Control наследование. Повторное использование шаблона?

StackOverflow https://stackoverflow.com/questions/2250661

Вопрос

У меня есть следующий сценарий:

[TemplatePart(Name = GoToEditModeButtonPart, Type = typeof(DoubleClickButton))]
public class ValueBoxWithLabel : ContentControl
{
    public const string GoToEditModeButtonPart = "GoToEditModeButtonPart";

    #region LabelText Dependency Property ...

    #region IsInEditMode Dependency Property ...

    public event EventHandler<ModeChangedEventArgs> ModeChanged;

    public ValueBoxWithLabel()
    {
        DefaultStyleKey = typeof (ValueBoxWithLabel);
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        //IsInEditMode invokes ModeChanged in the dependency property
        ((DoubleClickButton) GetTemplateChild(GoToEditModeButtonPart)).DoubleClick += (sender, args) => IsInEditMode = true;
    }

    private void InvokeModeChanged(ModeChangedEventArgs e)
    {
        EventHandler<ModeChangedEventArgs> mode = ModeChanged;
        if (mode != null)
            mode(this, e);
    }
}

Valuebox является важной панелью для любого входного ящика. Сейчас это просто, но будет повторно используется на протяжении всего приложения и будет содержать более сложный поведение и макет.

Текстовое поле в качестве входного использования необходимо использовать, поэтому я делаю это управление:

public class TextBoxWithLabel : ValueBoxWithLabel
{
    #region Text Dependency Property ...

    public TextBoxWithLabel()
    {
        DefaultStyleKey = typeof (TextBoxWithLabel);
    }
}

Затем у меня есть текущий generic.xaml, который не работает, но это дает представление о том, чего я хочу:

<ResourceDictionary>

<ControlTemplate x:Key="ValueBoxWithLabelTemplate">
    <StackPanel Style="{StaticResource ValueBoxWithLabelPanelStyle}">
        <TextBlock Style="{StaticResource LabelStyle}" Text="{TemplateBinding LabelText}" />
        <Grid>
            <ContentPresenter Content="{TemplateBinding Content}" />
            <local:DoubleClickButton Background="Black" x:Name="GoToEditModeButtonPart"></local:DoubleClickButton>
        </Grid>
    </StackPanel>
</ControlTemplate>

<Style TargetType="local:ValueBoxWithLabel">
    <Setter Property="Template" Value="{StaticResource ValueBoxWithLabelTemplate}" />
</Style>

<Style TargetType="local:TextBoxWithLabel">
    <Setter Property="Template" Value="{StaticResource ValueBoxWithLabelTemplate}" />
    <Setter Property="Content">
        <Setter.Value>
            <TextBox Style="{StaticResource ValueBoxStyle}" Text="{TemplateBinding Text}" />
        </Setter.Value>
    </Setter>
</Style>

Поскольку значение valueboxwithlabel наиболее используется с текстовым полетом, я хочу сделать управление для этого, который повторно использует один и тот же шаблон, поэтому мне не нужно копировать/вставить шаблон и иметь головы поддержания обоих с одинаковыми изменения.

Как я могу повторно использовать ValueboxWithLabeltemplate и только переопределить свойство контента, сохраняя оставшуюся часть шаблона?

Это было полезно?

Решение

Это интригующий подход. Я сам не пробовал, но похоже, что подход может работать.

Проблема, с которой у вас есть в настоящее время, заключается в том, что вы пытаетесь использовать Content собственность ContentPresenter. Анкет Однако это требует конкретного экземпляра управления, который в этом случае вы делаете с TextBox. Анкет Вы не можете использовать TemplateBinding в TextBox Потому что это не часть ControlTemplate.

Даже без TemplateBinding Проблема вы сможете создать только один элемент управления с ним в любом случае, так как вы не можете «повторно использовать» тот же экземпляр TextBox в более чем одном месте. Вот почему у нас есть шаблоны на первом месте.

Шаблоны полностью

Решение проблемы шаблона не должно быть таким трудным. Действительно обманчивая вещь - найти способ связать внутренний контроль контента специализированных элементов управления со свойствами специализированного класса. Это трудно, чтобы, когда вы не можете использовать TemplateBinding.

Сначала я просто намечу об изменениях, которые вам хотя бы внесли, чтобы получить элемент управления рендерингом:-

<ControlTemplate x:Key="ValueBoxWithLabelTemplate">
    <StackPanel Style="{StaticResource ValueBoxWithLabelPanelStyle}">
        <TextBlock Style="{StaticResource LabelStyle}" Text="{TemplateBinding LabelText}" />
        <Grid>
            <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" />
            <local:DoubleClickButton Background="Black" x:Name="GoToEditModeButtonPart"></local:DoubleClickButton>
        </Grid>
    </StackPanel>
</ControlTemplate>

А TextBoxWithLabel становится:-

<Style TargetType="local:TextBoxWithLabel">
    <Setter Property="Template" Value="{StaticResource ValueBoxWithLabelTemplate}" />
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <TextBox Style="{StaticResource ValueBoxStyle}"  />
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

Я думаю, что это (без тестирования) будет отображаться.

Проблема обязательного

Однако, как вы можете увидеть привязку на Text свойство отсутствует. Теперь есть несколько вещей, о которых я могу придумать, что может помочь вам решить эту проблему с обязательностью, но они включают либо злоупотребление DataContext или создание подклада ContentPresenter Чтобы помочь проходным свойствам от внешнего контроля до внутреннего. Оба настоящие уродливые.

Вывод

Для такого простого базового шаблона вам, вероятно, лучше дублировать шаблон, чем прыгать через все обручи, необходимые для достижения какого-то повторного использования.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top