abdou_dev
abdou_dev

Reputation: 827

How can I bind a ValueRange Maximum and Minimum using Dependency property?

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

Answers (1)

mm8
mm8

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

Related Questions