wpf 如何使用Dependency属性绑定ValueRange最大值和最小值?

8e2ybdfx  于 2023-10-22  发布在  其他
关注(0)|答案(1)|浏览(119)

我正在使用一个用户控件,它包含一个由多个用户控件使用的共享DataGrid。为了自定义每个用户控件的“Maximum”和“Minimum”值,我实现了Dependency Properties。如何有效地将这些属性从用户控件绑定到DataGrid?
我尝试了一种解决方案,但我始终收到默认值(0和100),这些值最初是在Int32RangeTable类中为“Maximum”和“Minimum”属性设置的。
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;
    }
}

调用MyUserControl的构造函数

// some code ...
var myusercontrol = MyUserControl(10,500);
k97glaaz

k97glaaz1#

要使Int32RangeChecker的绑定正常工作,您需要使用BindingProxy来捕获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>

相关问题