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

3
我有以下情境:
[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最常与TextBox一起使用,因此我希望为此创建一个控件,它可以重用相同的模板,因此我不需要复制/粘贴模板,并头疼地使两者随着相同的更改保持最新状态。

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

1个回答

1

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

您当前遇到的问题是正在尝试使用 ContentPresenterContent 属性。然而,这需要分配一个控件的具体实例,在这种情况下,您正在使用的是 TextBox。您不能在 TextBox 中使用 TemplateBinding,因为它不是 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的子类来帮助从外部控件传递属性到内部控件。两者都非常丑陋。

结论

对于这样一个简单的基本模板,您可能最好复制该模板,而不是跳过所有必要的步骤以实现某种重用。


感谢您的反馈。可能这个周末没有时间,但我会在周一第一时间尝试并汇报结果 :-) - Lars Udengaard
你好,安东尼。我试着使用你的解决方案,但是没有成功。 问题在于我无法访问控件模板中的“Parts”,因此上面的代码行将无法工作:((DoubleClickButton) GetTemplateChild(GoToEditStateButtonPart)).DoubleClick += (sender, args) => IsInEditMode = true;有什么想法吗? - Lars Udengaard
你在这个问题上提供了很多好的指针。由于我们当前项目的时间压力,我还没有深入挖掘。我可能会稍后发布更多内容。感谢您的输入。 - Lars Udengaard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接