WPF,XAML:CustomControl,如带有标题的TextBox

时间:2016-07-03 17:14:02

标签: c# wpf xaml custom-controls

我尝试使用变量标题创建 CustomControl ,例如 TextBox

我尝试学习创建CustomControl,我的异常是我的CustomControl(我称之为 TextBoxCustomControl )具有TextBox的所有属性和方法,并且还具有新属性 Caption

我希望这是对的,我的 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)));
        }
    }
}

主题\ Generic.xaml TextBoxCustomControl 的具体设计) - 有一个名为 innerTextBox

的TextBox
<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继承了所有属性(比如背景,宽度等),但事实并非如此。我做错了什么?

2 个答案:

答案 0 :(得分:1)

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

您正在应用的样式会覆盖所有TextBox的属性。设置模板时,需要对以后要绑定的所有属性使用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 :(得分:0)

  1. 首先,您所做的是复合控制。因此,从TextBox继承它并没有任何意义。如果您正在通过其他功能改进普通TextBox,则继承TextBox会有意义。

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

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

  3. 您尝试制作的内容已经显示为<HeaderedContentControl/>。您可以研究其源代码here或使用ILSpy。

  4. 示例:

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