Estoy escribiendo un control real NumericUpDown/Spinner
como un ejercicio para aprender la creación de control personalizado. Tengo la mayor parte del comportamiento que estoy buscando, incluida la coerción adecuada. Sin embargo, una de mis pruebas ha revelado un defecto.¿Por qué mi enlace de datos ve el valor real en lugar del valor coercionado?
Mi control tiene 3 propiedades de dependencia: Value
, MaximumValue
y MinimumValue
. Utilizo la coerción para asegurar que Value
permanezca entre el mínimo y el máximo, inclusive. Por ejemplo:
// In NumericUpDown.cs
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(int), typeof(NumericUpDown),
new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, HandleValueChanged, HandleCoerceValue));
[Localizability(LocalizationCategory.Text)]
public int Value
{
get { return (int)this.GetValue(ValueProperty); }
set { this.SetCurrentValue(ValueProperty, value); }
}
private static object HandleCoerceValue(DependencyObject d, object baseValue)
{
NumericUpDown o = (NumericUpDown)d;
var v = (int)baseValue;
if (v < o.MinimumValue) v = o.MinimumValue;
if (v > o.MaximumValue) v = o.MaximumValue;
return v;
}
Mi prueba es solo para garantizar que el enlace de datos funciona como yo esperaba. He creado un defecto WPF uso de las ventanas y la tiré en el siguiente XAML:
<Window x:Class="WpfApplication.MainWindow" x:Name="This"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:nud="clr-namespace:WpfCustomControlLibrary;assembly=WpfCustomControlLibrary"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<nud:NumericUpDown Value="{Binding ElementName=This, Path=NumberValue}"/>
<TextBox Grid.Row="1" Text="{Binding ElementName=This, Path=NumberValue, Mode=OneWay}" />
</Grid>
</Window>
con muy simple código subyacente:
public partial class MainWindow : Window
{
public int NumberValue
{
get { return (int)GetValue(NumberValueProperty); }
set { SetCurrentValue(NumberValueProperty, value); }
}
// Using a DependencyProperty as the backing store for NumberValue. This enables animation, styling, binding, etc...
public static readonly DependencyProperty NumberValueProperty =
DependencyProperty.Register("NumberValue", typeof(int), typeof(MainWindow), new UIPropertyMetadata(0));
public MainWindow()
{
InitializeComponent();
}
}
(estoy omitiendo el XAML para la presentación del control)
Ahora si ejecuto esto veo el valor del NumericUpDown
reflejado apropiadamente en el cuadro de texto, pero si escribo un valor fuera de rango, el valor fuera de rango se muestra en el cuadro de texto de prueba mientras que el NumericUpDown
muestra el valor correcto.
¿Es así como se supone que actúan los valores de coerción? Es bueno que se forzara en la interfaz de usuario, pero también esperaba que el valor forzado se ejecutara a través de la unión de datos.
Parece que la encuadernación no es compatible con el val. ¿Has probado el modo diff en TextBox? –