You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ControlTemplate中通过TemplateBinding绑定TextBox的Text属性

表单行控件效果参考

表单行样式预览

报错根因

ContentControl 类型本身没有定义Text依赖属性,直接在XAML中给该类型实例赋值Text属性,必然触发「成员不存在或不可访问」的解析错误。另外原有模板存在两个细节问题:

  • 模板内的TextBlock未绑定到父级的Content属性,传入的标签文本不会正常显示
  • TextBlock上设置的DockPanel.Dock附加属性无效,因为外层容器是StackPanel而非DockPanel,该属性不会生效
实现方案

两种常用实现方式,可根据项目复用需求选择:

方案1:附加属性实现(无需自定义控件,轻量快速)

不需要新建自定义控件,通过WPF附加属性机制扩展ContentControl的属性,用来承载文本框的双向绑定值,改动量最小。

  1. 先在项目中定义附加属性类:
public static class FormRowAssist
{
    public static readonly DependencyProperty InputValueProperty = DependencyProperty.RegisterAttached(
        "InputValue",
        typeof(string),
        typeof(FormRowAssist),
        new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)
    );

    public static void SetInputValue(DependencyObject element, string value) => element.SetValue(InputValueProperty, value);
    public static string GetInputValue(DependencyObject element) => (string)element.GetValue(InputValueProperty);
}
  1. 修改原有ControlTemplate,补全绑定逻辑:

注意TemplateBinding是单向(模板父级→模板内控件)的绑定,且对附加属性支持不佳,因此文本框的绑定用RelativeSource定位模板父级,开启双向绑定和输入实时更新

<UserControl.Resources>
    <ControlTemplate x:Key="formRow" TargetType="ContentControl">
        <StackPanel Margin="0 0 0 16">
            <!-- 补全标签文本绑定,显示Content传入的字段名称 -->
            <TextBlock 
                Margin="0 0 0 0"
                FontWeight="Bold"
                Text="{TemplateBinding Content}"/>
            <TextBox 
                Margin="0 8 0 0" 
                Text="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                Path=(local:FormRowAssist.InputValue), 
                Mode=TwoWay, 
                UpdateSourceTrigger=PropertyChanged}"/>
        </StackPanel>
    </ControlTemplate>
</UserControl.Resources>
  1. 使用时直接给附加属性赋值/绑定ViewModel即可,不会再触发解析错误:
<ScrollViewer Grid.Row="2" Grid.ColumnSpan="2">
    <StackPanel>
        <ComboBox Width="50" HorizontalAlignment="Left"/>
        <!-- 测试静态值直接给附加属性赋值即可,对接业务时替换为ViewModel属性绑定 -->
        <ContentControl 
            x:Name="FITextBox" 
            Content="FI Number: " 
            Template="{StaticResource formRow}" 
            local:FormRowAssist.InputValue="{Binding FiNumber, Mode=TwoWay}"/>
    </StackPanel>
</ScrollViewer>

方案2:自定义表单控件(适合高频复用场景)

如果这类表单项在项目中大量使用,直接自定义继承自ContentControl的专用控件,自带Text依赖属性,使用写法更直观。

  1. 定义自定义控件后台代码:
public class FormRow : ContentControl
{
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        nameof(Text),
        typeof(string),
        typeof(FormRow),
        new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)
    );

    public string Text
    {
        get => (string)GetValue(TextProperty);
        set => SetValue(TextProperty, value);
    }

    static FormRow()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(FormRow), new FrameworkPropertyMetadata(typeof(FormRow)));
    }
}
  1. 模板的TargetType改为自定义控件类型,内部可以直接用TemplateBinding绑定Text属性:
<ControlTemplate x:Key="formRow" TargetType="local:FormRow">
    <StackPanel Margin="0 0 0 16">
        <TextBlock FontWeight="Bold" Text="{TemplateBinding Content}"/>
        <TextBox Margin="0 8 0 0" Text="{TemplateBinding Text}"/>
    </StackPanel>
</ControlTemplate>
  1. 使用时直接实例化自定义控件,和最初预期的写法完全一致:
<local:FormRow 
    Content="FI Number: " 
    Template="{StaticResource formRow}"
    Text="{Binding FiNumber, Mode=TwoWay}"/>

内容的提问来源于stack exchange,提问作者Brendon Cheung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 19:15:33