如何在WPF自定义控件中显示基本控件

时间:2018-08-23 22:42:51

标签: c# wpf xaml

我想扩展一个TextBox控件以包含一个Label,其中Label从我的自定义控件的Content属性中获取其Label并自动附加到TextBox。 (这是一个愚蠢的例子,仅供学习。)

LabeledTextBox.cs

public class LabeledTextBox : TextBox
{
    static LabeledTextBox() =>
        DefaultStyleKeyProperty.OverrideMetadata(typeof(LabeledTextBox),
            new FrameworkPropertyMetadata(typeof(LabeledTextBox)));

    public static readonly DependencyProperty LabelProperty =
        DependencyProperty.Register("Label", typeof(string), typeof(LabeledTextBox));

    public string Label
    {
        get => (string)GetValue(LabelProperty);
        set => SetValue(LabelProperty, value);
    }
}

Themes / Generic.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyExample">

    <Style TargetType="{x:Type local:LabeledTextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:LabeledTextBox}">
                    <StackPanel Orientation="Vertical">
                        <Label Margin="0 0 0 4" Content="{TemplateBinding Label}" Target="{Binding ElementName=tbThis}" />

                        <!-- This doesn't work -->
                        <ContentPresenter x:Name="tbThis" />
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

我不知道如何显示TextBox基类。我已经搜索了SO和Google的前几个链接。看来我应该使用<ContentPresenter />,但它没有显示出来。我还尝试了几种将XAML中的ContentPresenter.ContentSource设置为无效的方法。

我知道我可以在ControlTemplate中添加一个TextBox,但这意味着要么丢失继承的TextBox的所有属性,要么需要手动附加它们,这违背了在{{1 }}。

2 个答案:

答案 0 :(得分:1)

Target绑定到TemplatedParent

<ControlTemplate TargetType="{x:Type local:LabeledTextBox}">
    <StackPanel>
        <Label Target="{Binding RelativeSource={RelativeSource TemplatedParent}}" Content="{TemplateBinding Label}"/>
        <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
            <ScrollViewer Focusable="False" x:Name="PART_ContentHost" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
        </Border>
    </StackPanel>
</ControlTemplate>

答案 1 :(得分:0)

您需要使用https://www.youtube.com/watch?v=x9lFB8-PjIg WPF magic:)

访问视觉元素

这是它的外观:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyExample">

    <Style TargetType="{x:Type local:LabeledTextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:LabeledTextBox}">
                    <StackPanel Orientation="Vertical">
                        <Label Margin="0 0 0 4" Content="{TemplateBinding Label}" Target="{Binding ElementName=tbThis}" />

                                <ScrollViewer x:Name="PART_ContentHost"
                                              HorizontalAlignment="Stretch"
                                              VerticalAlignment="Center"
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>