问题
I'm just mucking about with custom controls in silverlight and for the life of me i can't get the TemplateBindings to work. Can someone give this reduced version a once over to see if I'm missing something.
So my ControlTemplate in the generic.xaml looks like
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:NumericStepperControl;assembly=NumericStepperControl">
<Style TargetType="local:NumericStepper">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:NumericStepper">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="Black" BorderThickness="2" Width="50" Height="30">
<TextBlock Width="50" Height="30" Text="{TemplateBinding Value}" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
and my control class looks like:
namespace NumericStepperControl
{
public class NumericStepper : Control
{
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(NumericStepper), new PropertyMetadata(20));
public NumericStepper()
: base()
{
DefaultStyleKey = typeof( NumericStepper );
}
public int Value
{
get
{
return (int)GetValue(ValueProperty);
}
set
{
SetValue(ValueProperty, value);
}
}
}
}
I'm expecting when this runs the TextBlock will display the number 20. Any ideas as to why this isn't working?
As a side not i have a separate project which contains a ref to the NumericStepperControl assembly and when it runs the controls seem to build correctly.
Edit... after a bit more investigation i have discovered that if i change the type of the Value property to a string that works fine. Why does a text block not just call a toString on whatever is passed into it? Is there a way round this as i can see it happening a lot?
回答1:
After a bit of digging it turns out that the TextBlock actually doesn't call ToString on whatever is passed in. To work around this you must use a Converter to call a ToString for you.
Here's the rub though, TemplateBinding doesn't support Converters. You have to add the TemplateBinding to the DataContext and then use normal Binding in the Text property along with the converter.
So the TextBlock markup becomes
<TextBlock Width="50" Height="30" DataContext="{TemplateBinding Value}" Text="{Binding Converter={StaticResource NumberTypeToStringConverter}}" />
My custom converter:
public class NumberTypeToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
throw new NullReferenceException();
}
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
MethodInfo methodInfo = targetType.GetMethod("Parse");
if (methodInfo == null)
{
throw new MissingMethodException("The targetType to convert back to a Number must implement a Parse method");
}
return methodInfo.Invoke(null, new object[] { value });
}
}
This seems like a bit of a work around and i'd be interested to hear if it has any adverse implications. Also if anyone is reading this and there is anything wrong with my converter please let me know.
Cheers
回答2:
There are different approaches to get arround the problem. Found this description by Marek Latuskiewicz.
来源:https://stackoverflow.com/questions/755877/templatebindings-in-custom-controls