TemplateBindings em controles personalizados
-
09-09-2019 - |
Pergunta
Eu estou apenas mucking com controles personalizados no Silverlight e para a vida de mim eu não posso obter os TemplateBindings ao trabalho. Alguém pode dar a esta versão reduzida uma vez mais para ver se eu estou faltando alguma coisa.
Assim, a minha ControlTemplate nos olhares generic.xaml como
<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>
e meu controle aparência de classe como:
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);
}
}
}
}
Estou esperando quando esta corre o TextBlock exibirá o número 20. Alguma idéia de por que isso não está funcionando?
Como um lado não tenho um projeto separado que contém uma referência ao NumericStepperControl montagem e quando ele é executado os controles parecem construir corretamente.
Editar ... depois de um pouco mais de investigação eu descobri que se eu mudar o tipo da propriedade Value para uma cadeia que funciona bem. Por que um bloco de texto não apenas chamar um toString em tudo o que é passado para ele? Existe uma maneira de contornar isso como eu posso ver isso acontecendo muito?
Solução
Depois de um pouco de escavação verifica-se que o TextBlock realmente não chama ToString sobre o que é passado. Para contornar isso, você deve usar um conversor para chamar um ToString para você.
Aqui está o busílis, porém, TemplateBinding não suporta conversores. Você tem que adicionar o TemplateBinding ao DataContext e, em seguida, o uso normal de ligação na propriedade Text juntamente com o conversor.
Assim, a marcação TextBlock se torna
<TextBlock Width="50" Height="30" DataContext="{TemplateBinding Value}" Text="{Binding Converter={StaticResource NumberTypeToStringConverter}}" />
Meu conversor personalizado:
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 });
}
}
Este parece ser um pouco de um em torno do trabalho e eu estaria interessado em saber se ele tem quaisquer implicações negativas. Além disso, se alguém está lendo isso e não há nada de errado com o meu conversor por favor me avise.
Felicidades
Outras dicas
Existem diferentes abordagens para obter espalhados pelo problema. Encontrado este descrição por Marek Latuskiewicz .