I have a custom TextBox that adds MinMaxValidationRule when both Min and Max properties are set
public class TextBox2 : TextBox
{
public static readonly DependencyProperty MinProperty = DependencyProperty.Register(
nameof(Min), typeof(double?), typeof(TextBox2),
new PropertyMetadata(null, MinMaxChangeCallback));
public double? Min
{
get => (double?)GetValue(MinProperty);
set => SetValue(MinProperty, value);
}
public static readonly DependencyProperty MaxProperty = DependencyProperty.Register(
nameof(Max), typeof(double?), typeof(TextBox2),
new PropertyMetadata(null, MinMaxChangeCallback));
public double? Max
{
get => (double?)GetValue(MaxProperty);
set => SetValue(MaxProperty, value);
}
private static void MinMaxChangeCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBox2 = (TextBox2)d;
if (textBox2.Min == null || textBox2.Max == null)
return;
var binding = textBox2.GetBindingExpression(TextProperty);
var validationRules = binding
.ParentBinding
.ValidationRules;
validationRules.Clear();
var minMaxValidationRule = new MinMaxValidationRule((double)textBox2.Min, (double)textBox2.Max)
{
ValidatesOnTargetUpdated = true
};
validationRules.Add(minMaxValidationRule);
binding.UpdateTarget(); // triggers the validation rule
}
}
The validation rule is defined as follows
public class MinMaxValidationRule : ValidationRule
{
public double Min { get; }
public double Max { get; }
public MinMaxValidationRule(double min, double max)
{
Min = min;
Max = max;
}
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if (double.TryParse((string)value, out var d)
&& d <= Max
&& d >= Min)
return ValidationResult.ValidResult;
return new ValidationResult(false, $"Value must be in [{Min},{Max}]");
}
}
I've created a ItemsControl to display a list of ItemInfo objects
<ItemsControl
Margin="8"
ItemsSource="{Binding ItemInfos}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type testApp:ItemInfo}">
<testApp:TextBox2
Style="{StaticResource MaterialDesignOutlinedTextBox}"
Width="400"
Margin="12"
Padding="8"
Min="{Binding Min}"
Max="{Binding Max}"
Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
ItemInfos = new()
{
new()
{
Min = 0,
Max = 100,
Value = 50
},
new()
{
Min = 200,
Max = 300,
Value = 250
},
};
}
public List<ItemInfo> ItemInfos { get; }
}
public class ItemInfo
{
public double Min { get; set; }
public double Max { get; set; }
public double Value { get; set; }
}
When writing "2" in the first TextBox (changing the value from 50 to 502), WPF is using the validation rule of the second textBox, but I expect that each TextBox uses its own ValidationRule.
Any idea on how to fix this?
