簡體   English   中英

帶參數的ValidationRule

[英]ValidationRule with parameters

我正在使用C#和WPF開發應用程序,我有自己的滑塊自定義控件。 和文本框在同一窗口上。 我的滑塊的所有屬性都是DependencyProperty

我使用文本框更改滑塊的屬性。 我想在文本框上使用ValidationRule 我編寫了自己的ValidationRule(從ValidationRule類派生)。 我想將一些參數傳遞給該ValidationRule 這是代碼:

文本框:

<TextBox HorizontalAlignment="Left" Height="24" Margin="10,169,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="40" Style="{DynamicResource archiveSearchTextBox}" MaxLength="3" HorizontalContentAlignment="Center" TabIndex="2">
        <TextBox.Text>
            <Binding UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" ElementName="gammaSlider" Path="LeftThumbValue" NotifyOnValidationError="True" ValidatesOnExceptions="True" ValidatesOnDataErrors="True">
                <Binding.ValidationRules>
                    <ExceptionValidationRule/>
                    <local:ZeroTo255MinMax>
                        <local:ZeroTo255MinMax.Parameters>
                            <local:ValidationParameters NumberCombineTo="{Binding ElementName=gammaSlider, Path=RightThumbValue}" ValTypeFor0to255="ShouldBeSmaller"/>
                        </local:ZeroTo255MinMax.Parameters>
                    </local:ZeroTo255MinMax>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>

ZeroTo255MinMax驗證規則:

 public class ZeroTo255MinMax : ValidationRule
{
    private ValidationParameters _parameters = new ValidationParameters();
    public ValidationParameters Parameters
    {
        get { return _parameters; }
        set { _parameters = value; }
    }

    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        string numberStr = value as string;
        int val;

        if (int.TryParse(numberStr, out val))
        {
            if (val < 0 || val > 255)
                return new ValidationResult(false, "");
            else if (Parameters.ValTypeFor0to255 == ValidationParameters.ValTypes.ShouldBeBigger)
            {
                if (val <= Parameters.NumberCombineTo || val - Parameters.NumberCombineTo < 2)
                    return new ValidationResult(false, "");
            }
            else if (Parameters.ValTypeFor0to255 == ValidationParameters.ValTypes.ShouldBeSmaller)
            {
                if (val >= Parameters.NumberCombineTo || Parameters.NumberCombineTo - val < 2)
                    return new ValidationResult(false, "");
            }
            return new ValidationResult(true, "");
        }
        else
            return new ValidationResult(false, "");
    }
}

public class ValidationParameters : DependencyObject
{
    public enum ValTypes { ShouldBeSmaller, ShouldBeBigger };
    public static readonly DependencyProperty NumberCombineToProperty = DependencyProperty.Register("NumberCombineTo", typeof(int), typeof(ValidationParameters), new PropertyMetadata(0, new PropertyChangedCallback(OnNumberCombineToChanged)));
    public static readonly DependencyProperty ValTypeFor0to255Property = DependencyProperty.Register("ValTypeFor0to255", typeof(ValTypes), typeof(ValidationParameters), new PropertyMetadata(ValTypes.ShouldBeBigger));

    private static void OnNumberCombineToChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { d.CoerceValue(NumberCombineToProperty); }

    public int NumberCombineTo
    {
        get { return (int)GetValue(NumberCombineToProperty); }
        set { SetValue(NumberCombineToProperty, value); }
    }

    public ValTypes ValTypeFor0to255
    {
        get { return (ValTypes)GetValue(ValTypeFor0to255Property); }
        set { SetValue(ValTypeFor0to255Property, value); }
    }
}

我的猜測是,一切都很好,但問題是, NumberCombineTo參數設置為default (0) 即使我改變gammaSlider的RightThumbValue財產 我需要更新NumberCombineTo當財產RightThumbValue改變。

我根據您在此處提供的摘錄編寫了一個簡單的完整代碼示例,我相信我能夠重現您遇到的基本問題。

如果您在調試器中運行代碼,並查看“輸出”窗口,則可能會看到部分消息:

找不到目標元素的管理FrameworkElement或FrameworkContentElement

WPF綁定系統需要這些元素之一才能查找源元素的名稱(即ElementName屬性的對象)。 但是在這種情況下,您試圖綁定對象的屬性,該對象本身既不是框架相關元素,也不是以WPF可見的方式與一個元素相關。 因此,在嘗試配置綁定時失敗。

我看過幾篇不同的文章,建議通過“代理對象”解決此問題。 這通常遵循以下模式:聲明綁定到包含對象的DataContext的資源,然后將該對象用作綁定的Source 但是,對我來說,正確設置此設置似乎很棘手,這取決於能否設置一個特定的DataContext對象,該對象包含實際上要綁定的屬性。 隨着無框架元素綁定數量的增加,您可以采用此技術的程度受到限制。

例如:
不繼承DataContext時如何綁定數據
在WPF中將虛擬分支附加到邏輯樹
甚至在SO, WPF上也出現此錯誤:找不到目標元素的控制FrameworkElement

相反,在我看來,這是后台代碼更好地工作的情況之一。 只需幾行代碼即可顯式設置綁定,並且完全避免了WPF是否實際上可以找到要綁定的對象的問題。

我總結了一個如下所示的XAML示例:

<Window x:Class="TestSO28645688ValidationRuleParameter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestSO28645688ValidationRuleParameter"
        Title="MainWindow" Height="350" Width="525">
  <Window.Resources>
    <local:ValidationParameters x:Key="validationParams1"
                                    ValTypeFor0to255="ShouldBeSmaller"/>
  </Window.Resources>
  <StackPanel>
    <Slider x:Name="slider1" Value=".25" />
    <Slider x:Name="slider2" Value=".5"/>
    <TextBlock Text="{Binding ElementName=slider1, Path=Value,
               StringFormat=slider1.Value: {0}}" />
    <TextBlock Text="{Binding ElementName=slider2, Path=Value,
               StringFormat=slider2.Value: {0}}" />
    <TextBlock Text="{Binding Source={StaticResource validationParams1},
                              Path=NumberCombineTo,
                              StringFormat=validationParams1.NumberCombineTo: {0}}" />
    <TextBox x:Name="textBox1" HorizontalAlignment="Left" VerticalAlignment="Top"
             Height="24" Width="400"
             Margin="5" TextWrapping="Wrap"
             MaxLength="3" HorizontalContentAlignment="Center" TabIndex="2">
      <TextBox.Text>
        <Binding UpdateSourceTrigger="PropertyChanged" Mode="TwoWay"
                 ElementName="slider1" Path="Value" NotifyOnValidationError="True"
                 ValidatesOnExceptions="True" ValidatesOnDataErrors="True">
          <Binding.ValidationRules>
            <ExceptionValidationRule/>
            <local:ZeroTo255MinMax Parameters="{StaticResource validationParams1}"/>
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    </TextBox>
  </StackPanel>
</Window>

此處與您的代碼不同的主要是,我將ValidationParameters對象放入窗口的資源中。 這使我可以輕松地從背后的代碼中引用它以進行綁定。

(當然,其余的代碼也有所不同,但是沒有任何有意義的方式。我覺得,對於基本示例,只使用兩個單獨的Slider控件Slider簡單了,因為它內置於WPF中,並在窗口中提供TextBlock元素以便更輕松地了解發生了什么)。

后面的代碼如下所示:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Binding binding = new Binding();

        binding.Source = slider2;
        binding.Path = new PropertyPath(Slider.ValueProperty);

        ValidationParameters validationParams = (ValidationParameters)Resources["validationParams1"];

        BindingOperations.SetBinding(validationParams, ValidationParameters.NumberCombineToProperty, binding);
    }
}

換句話說,它只需創建一個新的Binding對象,分配源對象和屬性,檢索ValidationParameters對象,這是我們想要的是對象+屬性綁定,然后設置上的結合ValidationParameters對象的NumberCombineTo屬性。

當我這樣做時, NumberCombineTo屬性被正確地更新為slider2.Value當值的變化,它可以使用Validate()的方法ValidationRule對象被調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM