WPF,XAML: CustomControl like TextBox with caption

WPF, XAML: CustomControl like TextBox with caption

我尝试创建一个 CustomControl,就像一个带有变量 captionTextBox

我尝试学习创建 CustomControl,我的例外是我的 CustomControl(我称之为 TextBoxCustomControl)具有 TextBox 的所有属性和方法,并且还有新的 属性 标题.

我希望这是正确的,我的 TextBoxCustomControl 继承自 TextBox 而不是 Control.


TextBoxCustomControl.cs

namespace CustomControlProject
{
    public class TextBoxCustomControl : TextBox
    {
        public static readonly DependencyProperty CaptionProperty = DependencyProperty.Register("Caption", typeof(string), typeof(TextBoxCustomControl), new FrameworkPropertyMetadata(String.Empty));

        public string Caption
        {
            get { return (string)GetValue(CaptionProperty); }
            set { SetValue(CaptionProperty, value); }
        }

        static TextBoxCustomControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxCustomControl), new FrameworkPropertyMetadata(typeof(TextBoxCustomControl)));
        }
    }
}

Themes\Generic.xaml(针对TextBoxCustomControl的具体设计)——有一个名为innerTextBox

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


    <Style x:Name="CustomStyle" TargetType="local:TextBoxCustomControl" BasedOn="{StaticResource {x:Type TextBox}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:TextBoxCustomControl}">
                    <WrapPanel Orientation="Vertical">
                        <TextBox x:Name="innerTextBox" />
                        <Label Content="{TemplateBinding Caption}" />
                    </WrapPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

MainWindow.xaml 中,我使用我的 TextBoxCustomControl 并为其指定一些属性。

<Window x:Class="CustomControlProject.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:CustomControlProject"
        Title="MainWindow" Height="350" Width="525">
    <WrapPanel>
        <local:TextBoxCustomControl Width="287" Background="Yellow" Caption="Fill the nickname, please." />
    </WrapPanel>
</Window>

我的期望是我的 TextBoxCustomControl 中的 innerTextBox 继承所有属性(如背景、宽度等),但那并没有发生。我做错了什么?

首先,继承自 Control 的 CustomControl 与由多个 Control 组成的 UserControl 之间存在差异。

您应用的样式覆盖了文本框的所有属性。设置模板时,您需要为以后要绑定的所有属性使用 TemplateBinding。否则,将无法再从外部访问它们。

对于您要实现的目标,您可以跳过样式并将 XAML 更改为

<Window x:Class="CustomControlProject.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:CustomControlProject"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <local:TextBoxCustomControl 
            x:Name="CustomBox" 
            Width="287" Background="Yellow" 
            Caption="Fill the nickname, please." />
        <Label 
            Content="{Binding ElementName=CustomBox, Path=Caption}" />
    </StackPanel>
</Window>

要使其成为一体,您需要构建一个 UserControl。

  1. 首先你做的是复合控件。所以,从 TextBox 继承它没有任何意义。如果您正在改进具有附加功能的普通 TextBox,那么从 TextBox 继承是有意义的。

  2. 您认为您在自定义控件级别设置的任何内容都会被子控件继承的想法是错误的。如果您想这样做,请对个人 properties 使用 TemplateBinding。例如; <TextBox x:Name="innerTextBox" Width="{TemplateBinding Width}"/> .

    注意:某些属性(FontSize、FontFamily)会自动传播,无需任何额外工作。

  3. 您尝试制作的内容已经作为 <HeaderedContentControl/> 存在。你可以研究它的源代码 here 或者使用 ILSpy.

样本:

    <HeaderedContentControl>
        <HeaderedContentControl.Header>
            <Border>
                <TextBlock Text="Name please !"/>
            </Border>
        </HeaderedContentControl.Header>
        <HeaderedContentControl.Content>
            <TextBox />
        </HeaderedContentControl.Content>
    </HeaderedContentControl>