【问题标题】:Silverlight custom control inheritance. Reusing the template?Silverlight 自定义控件继承。重用模板?
【发布时间】:2011-01-16 01:52:59
【问题描述】:

我有以下情况:

[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 属性来保留模板的其余部分?

【问题讨论】:

    标签: silverlight inheritance custom-controls controltemplate reusability


    【解决方案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 的子类来帮助将属性从外部控件传递到内部控件一。两个都很丑。

    结论

    对于这样一个简单的基本模板,您最好复制模板,而不是跳过所有必要的环节来实现某种重用。

    【讨论】:

    • 感谢您的反馈。这个周末可能不会有时间,但我会在星期一第一件事尝试,然后报告:-)
    • 你好,安东尼。我到处尝试你的解决方案,但没有运气。问题是我无法访问控件模板中的“部件”,因此上面的以下行将不起作用: ((DoubleClickButton) GetTemplateChild(GoToEditStateButtonPart)).DoubleClick += (sender, args) => IsInEditMode =真的;有什么想法吗?
    • 你有很多关于这个问题的好建议。由于我们当前项目的时间压力。我还没有时间深入挖掘。我以后可能会发布更多。感谢您的意见。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多