我正在使用一个非常简单的无外观控件,我似乎无法使其中一个模板绑定起作用。在控件中我有两个依赖属性,一个是字符串工作,而一个是int工作,
csharp代码如下所示:
using System;
using System.Windows;
using System.Windows.Controls;
namespace ControlDemo
{
public class TextControlLookless : Control
{
#region Title
public static readonly DependencyProperty ChartTitleProperty =
DependencyProperty.Register("ChartTitle", typeof(string), typeof(TextControlLookless),
null);
public String ChartTitle
{
get { return (string)GetValue(ChartTitleProperty); }
set
{
SetValue(ChartTitleProperty, value);
}
}
#endregion
#region Value
public static readonly DependencyProperty ChartValueProperty =
DependencyProperty.Register("ChartValue", typeof(int), typeof(TextControlLookless),
null);
public int ChartValue
{
get { return (int)GetValue(ChartValueProperty); }
set
{
SetValue(ChartValueProperty, value);
}
}
#endregion
#region ctor
public TextControlLookless()
{
this.DefaultStyleKey = typeof(TextControlLookless);
}
#endregion
}
}
控件的xaml如下所示:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ControlDemo">
<Style TargetType="local:TextControlLookless">
<Setter Property="ChartTitle" Value="Set Title" />
<Setter Property="ChartValue" Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TextControlLookless">
<Grid x:Name="Root">
<Border BorderBrush="Black" BorderThickness="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="{TemplateBinding ChartTitle}" />
<TextBlock Text="{TemplateBinding ChartValue}" Grid.Row="1" />
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
当我把它放在页面上时,我可以看到ChartTitle(设置标题,或者我设置的任何标题),但ChartValue从不显示。如果我将其类型更改为字符串,它确实会显示,所以我必须遗漏一些东西。
答案 0 :(得分:0)
问题在于TemplateBinding
是比Binding
更原始的操作。 Binding
是一个实际的类,包含一些有用的功能,包括在其他数据类型之间来回隐式转换字符串。
TemplateBinding
纯粹是一个标记指令,在您的情况下,最重要的是不为您进行类型转换。因此,绑定到Text
的{{1}}属性的依赖项属性必须是字符串。
您有两种选择: -
一种选择是使用TemplateBinding为TextBlock
提供一个名称,并在TextBlock
属性更改回调中指定其Text
: -
ChartValue
xaml的样子: -
#region Value
public static readonly DependencyProperty ChartValueProperty =
DependencyProperty.Register("ChartValue", typeof(int), typeof(TextControlLookless),
new PropertyMetadata(0, OnChartValuePropertyChanged));
private static void OnChartValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TextControlLookless source = d as TextControlLookless;
source.Refresh();
}
public int ChartValue
{
get { return (int)GetValue(ChartValueProperty); }
set
{
SetValue(ChartValueProperty, value);
}
}
#endregion
private TextBlock txtChartValue { get; set; }
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
txtChartValue = GetTemplateChild("txtChartValue") as TextBlock;
Refresh();
}
private void Refresh()
{
if (txtChartValue != null)
{
txtChartValue.Text = ChartValue.ToString();
}
}
另一种选择是为字符串类型的值创建私有依赖项属性: -
<TextBlock x:Name="txtChartValue" Grid.Row="1" />
xaml的样子: -
#region Value
public static readonly DependencyProperty ChartValueProperty =
DependencyProperty.Register("ChartValue", typeof(int), typeof(TextControlLookless),
new PropertyMetadata(0, OnChartValuePropertyChanged));
private static void OnChartValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
d.SetValue(ChartValueStrProperty, e.NewValue.ToString());
}
private static readonly DependencyProperty ChartValueStrProperty =
DependencyProperty.Register("ChartValueStr", typeof(string), typeof(TextControlLookless),
new PropertyMetadata("0"));
public int ChartValue
{
get { return (int)GetValue(ChartValueProperty); }
set
{
SetValue(ChartValueProperty, value);
}
}
#endregion
请注意 <TextBlock Text="{TemplateBinding ChartValueStr}" Grid.Row="1" />
是私有的,我没有打扰创建一个标准的.NET属性来覆盖它。 ChartValueStrProperty
实际上使用您指定的属性名称后缀为“Property”,然后在目标类型上查找静态字段。
这两种方法都有其优点和缺点。第一种方法是更常见的模式,但需要更多的代码并且灵活性较差(显示值的控件必须是TextBlock)。第二种是更灵活,使用更少的代码,但有点不正统。