Reputation: 827
I'm working with a user control that includes a shared DataGrid used by multiple user controls. To customize the 'Maximum' and 'Minimum' values for each user control, I've implemented Dependency Properties. How can I effectively bind these properties from my user control to the DataGrid for this purpose?
I've tried a solution, but I consistently receive the default values (0 and 100) that are initially set in the Int32RangeChecker class for the 'Maximum' and 'Minimum' properties.
ValueRangeRule.cs
public class ValueRangeRule: ValidationRule {
private Int32RangeChecker _validRange;
public Int32RangeChecker ValidRange {
get {
return _validRange;
}
set {
_validRange = value;
}
}
public ValueRangeRule() {}
public override ValidationResult Validate(object value, CultureInfo cultureInfo) {
double MyValue = 0;
try {
if (((string) value).Length > 0)
MyValue = double.Parse((string) value);
} catch (Exception e) {
return new ValidationResult(false, $ "Illegal characters or {e.Message}");
}
if ((MyValue <= ValidRange.Minimum) || (MyValue >= ValidRange.Maximum)) {
return new ValidationResult(false,
$ "Please enter a value in the range: {ValidRange.Minimum}-{ValidRange.Maximum}.");
}
return ValidationResult.ValidResult;
}
}
public class Int32RangeChecker: DependencyObject {
public int Minimum {
get {
return (int) GetValue(MinimumProperty);
}
set {
SetValue(MinimumProperty, value);
}
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register(nameof(Minimum), typeof (int), typeof (Int32RangeChecker), new UIPropertyMetadata(0));
public int Maximum {
get {
return (int) GetValue(MaximumProperty);
}
set {
SetValue(MaximumProperty, value);
}
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register(nameof(Maximum), typeof (int), typeof (Int32RangeChecker), new UIPropertyMetadata(100));
}
UserControl Xaml
<TextBox.Text>
<Binding Path="MyValue" Converter="{StaticResource ConvertString}" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<!--<local:ValueRangeRule></local:ValueRangeRule>-->
<local:ValueRangeRule>
<local:ValueRangeRule.ValidRange>
<local:Int32RangeChecker
Minimum="{Binding MinRange, RelativeSource={RelativeSource AncestorType={x:Type local:MyForm}},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Maximum="{Binding MaxRange, RelativeSource={RelativeSource AncestorType={x:Type local:MyForm}},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
/>
</local:ValueRangeRule.ValidRange>
</local:ValueRangeRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
MyUserControl Code behind :
public MyUserControl(): INotifyPropertyChanged, UserControl {
private int minRange;
private int maxRange;
public int MaxRange {
get {
return maxRange;
}
set {
maxRange = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged();
}
}
public int MinRange {
get {
return maxRange;
}
set {
maxRange = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged();
}
}
public MyUserControl(int minRange = 0, int maxRange = 500)
{
// other code
MaxRange = minRange;
MinRange = maxRange;
}
}
Calling Constructor of MyUserControl
// some code ...
var myusercontrol = MyUserControl(10,500);
Upvotes: 0
Views: 64
Reputation: 169200
For the bindings to your Int32RangeChecker
to work, you need to use a BindingProxy
to capture the DataContext
:
public class BindingProxy : Freezable
{
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}
XAML:
<TextBox>
<TextBox.Resources>
<local:BindingProxy x:Key="proxy"
Data="{Binding RelativeSource={RelativeSource AncestorType=local:MyUserControl}}"/>
</TextBox.Resources>
<TextBox.Text>
<Binding Path="MyValue" Converter="{StaticResource ConvertString}" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:ValueRangeRule>
<local:ValueRangeRule.ValidRange>
<local:Int32RangeChecker
Minimum="{Binding Data.MinRange, Source={StaticResource proxy}}"
Maximum="{Binding Data.MaxRange, Source={StaticResource proxy}}"/>
</local:ValueRangeRule.ValidRange>
</local:ValueRangeRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Upvotes: 1