Silverlight自定义控件继承。重用模板?

时间:2010-02-12 09:12:04

标签: silverlight inheritance custom-controls controltemplate reusability

我有以下情况:

[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是任何输入框的面板必不可少的。它现在很简单,但将在整个应用程序中重用,并将包含更复杂的行为和布局。

TextBox作为输入是必须使用的,因此我做了这个控件:

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最常用于TextBox,我想对此进行控制,它重复使用相同的模板,所以我不需要复制/粘贴模板,并且保持最新状态同样的变化。

如何重用ValueBoxWithLabelTemplate并仅覆盖保留模板其余部分的content属性?

1 个答案:

答案 0 :(得分:1)

这是一种有趣的方法。我自己没试过,但看起来这种方法可能会奏效。

您目前遇到的问题是您正在尝试使用Content的{​​{1}}属性。但是,这需要分配一个控件的具体实例,在这种情况下,您正在使用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的子类来帮助从外部传递属性控制内在的。两者都很难看。

<强>结论

对于这样一个简单的基本模板,你可能最好不要复制模板而不是跳过实现某种重用所需的所有箍。