WPF TemplateBinding不适用于每个属性

时间:2018-06-04 08:29:34

标签: c# wpf

我创建了自定义控件,但TemplateBinding不适用于每个属性? 如果我使用只转发原始值的虚拟转换器,模板绑定会开始工作。 具有相同问题的简化示例:

<Style TargetType="{x:Type controls:ElipticProgressBar}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:ElipticProgressBar}">
                <ControlTemplate.Resources>
                    <converters:DebugConverter x:Key="DebugConverter"/>
                </ControlTemplate.Resources>
                <StackPanel>
                    <!--BarColor works always-->
                    <!--BarTickness works-->
                    <Label Background="{TemplateBinding BarColor}" Content="{TemplateBinding BarTickness}"/>
                    <!--BarTickness does not works-->
                    <TextBlock Background="{TemplateBinding BarColor}" Text="{TemplateBinding BarTickness}"/>
                    <!--BarTickness works-->
                    <TextBlock Background="{TemplateBinding BarColor}" Text="{Binding BarTickness, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"/>
                    <!--BarTickness works-->
                    <TextBlock Background="{TemplateBinding BarColor}" Text="{TemplateBinding BarTickness, Converter={StaticResource DebugConverter}}"/>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

返回代码:

public class ElipticProgressBar : Control
{
    static ElipticProgressBar()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ElipticProgressBar), new FrameworkPropertyMetadata(typeof(ElipticProgressBar)));
    }

    public static readonly DependencyProperty BarTicknessProperty = DependencyProperty.Register(
        "BarTickness", typeof(int), typeof(ElipticProgressBar), new FrameworkPropertyMetadata(default(int)));

    public int BarTickness
    {
        get { return (int)GetValue(BarTicknessProperty); }
        set { SetValue(BarTicknessProperty, value); }
    }

    public static readonly DependencyProperty BarColorProperty = DependencyProperty.Register(
        "BarColor", typeof(Brush), typeof(ElipticProgressBar), new FrameworkPropertyMetadata(default(Brush)));

    public Brush BarColor
    {
        get { return (Brush)GetValue(BarColorProperty); }
        set { SetValue(BarColorProperty, value); }
    }
}

用法:

controls:ElipticProgressBar BarTickness="30" BarColor="Orange"

DebugConverter:

public class DebugConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }
}

2 个答案:

答案 0 :(得分:1)

{TemplateBinding}是绑定的优化版本,具有一些限制。

在这种情况下,您需要将BarThickness属性的类型更改为string才能将其直接绑定到Text的{​​{1}}属性TextBlock

答案 1 :(得分:0)

cmd + v

docs state
  

模板场景的绑定的优化形式,类似于使用{TemplateBinding}

构造的绑定

有一些限制 - 最重要的是只能在可视树中使用!

这对您的具体案例意味着什么:虽然您不能使用

{Binding RelativeSource={RelativeSource TemplatedParent}}

你可以(并且必须)使用

<TextBlock Text="{TemplateBinding BarTickness}" />

因为<TextBlock Text="{Binding BarTickness, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" /> 属性属于TextBlock.Text类型而string属性不属于BarTickness属性。

{TemplateBinding}没有做那种转换;这就是为什么你需要使用更通用的{Binding}或转换器,其两种方法

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    return value;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    return value;
}

将实际值转换为object