wpf WPF如何在文本框中使用验证规则而不创建额外的属性来绑定到对话框?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22775895/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 11:24:53  来源:igfitidea点击:

WPF How to use a validation rule in a textbox without creating an extra property to bind to in dialogbox?

c#wpfvalidationxaml

提问by James Joshua Street

so I have one example that is working here:

所以我有一个在这里工作的例子:

     <TextBox.Style>
          <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
              <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip"
                          Value="{Binding RelativeSource={RelativeSource Self}, 
                        Path=(Validation.Errors), Converter={StaticResource ValidationConverter}}"
                        />
              </Trigger>
              <Trigger Property="Validation.HasError" Value="false">
                <Setter Property="ToolTip"
                          Value="GraphPenWidth" />
                <Setter Property="Background" 
                    Value="Blue"
                    />
              </Trigger>
            </Style.Triggers>
          </Style>
        </TextBox.Style>
        <TextBox.Text>
          <Binding Path="GraphPenWidth" UpdateSourceTrigger="PropertyChanged"  Mode="TwoWay">
            <Binding.ValidationRules>
              <DaedalusValidationRules:IntegerValidationRule />
            </Binding.ValidationRules>
          </Binding>
        </TextBox.Text>

However, is there any way to use a validation rule without binding to a datacontext?

但是,有没有办法在不绑定到数据上下文的情况下使用验证规则?

I am trying to make a generic dialogbox that I can pass various validation rules to. However, I found after a while that even when I create the validation rule in xaml it wasn't working correctly. I had read that I could just bind the TextBox's Text Property to itself, but this did not work.

我正在尝试制作一个通用对话框,我可以将各种验证规则传递给它。但是,一段时间后我发现即使我在 xaml 中创建验证规则,它也无法正常工作。我读过我可以将 TextBox 的 Text 属性绑定到自身,但这不起作用。

However, when I put a breakpoint in the ValidationRule it seems to be getting called at the correct point when I insert data. In addition the style appears to be working because the background is blue. That leads me to believe that Validation.HasError is never becoming true or is becoming true and changing back so fast that I can't see the change.

但是,当我在 ValidationRule 中放置断点时,它似乎在我插入数据时在正确的点被调用。此外,该样式似乎有效,因为背景是蓝色的。这让我相信 Validation.HasError 永远不会变成真的,或者正在变成真的并且变回如此之快以至于我看不到变化。

The validation rule gets called after every letter I type, yet the textbox doesn't update to show haserror = true. why is this?

在我输入每个字母后都会调用验证规则,但文本框不会更新以显示 haserror = true。为什么是这样?

Am I just not allowed to bind a property to itself? is there any other way I can use a validation rule without having a binding or do I just always have to create an extra property to bind to? The shortest fix is just to create an extra text property and bind it pointlessly, but I had hoped that wasn't necessary.

我只是不允许将属性绑定到自身吗?有没有其他方法可以在没有绑定的情况下使用验证规则,还是我总是需要创建一个额外的属性来绑定?最短的解决方法就是创建一个额外的文本属性并毫无意义地绑定它,但我希望这不是必需的。

 <TextBox    
    Margin="3"
    Height="25"
    VerticalAlignment="Center"
    VerticalContentAlignment="Center"
    HorizontalContentAlignment="Left"
    Grid.Column="1"
    x:Name="MainTextBox"
    >
    <TextBox.Text>
      <Binding RelativeSource="{RelativeSource Self}" Path="Text" UpdateSourceTrigger="PropertyChanged">
        <Binding.ValidationRules>
          <rules:IntegerValidationRule />
        </Binding.ValidationRules>
      </Binding>
    </TextBox.Text>

    <TextBox.Style>
      <Style TargetType="{x:Type TextBox}">
        <Style.Triggers>
          <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip" 
                    Value="{Binding RelativeSource={x:Static RelativeSource.Self}, 
                            Path=(Validation.Errors), Converter={StaticResource ValidationConverter}}"
                    />
            <Setter Property="Background" 
                    Value="Red"
                    />
          </Trigger>
          <Trigger Property="Validation.HasError" Value="false">
            <Setter Property="ToolTip"
                          Value="Default Signal Height Percentage" />
            <Setter Property="Background" 
                    Value="Blue"
                    />
          </Trigger>
        </Style.Triggers>
      </Style>
    </TextBox.Style>
  </TextBox>

So I actually managed to get the validation working in xaml by just making a property to bind against called Text on the GenericDialogBox and then binding that Text property to the Text Property of the Textbox. However, I can't seem to get the same code to work in the code behind.

因此,我实际上只是通过创建一个属性来绑定 GenericDialogBox 上的被调用的 Text,然后将该 Text 属性绑定到 Textbox 的 Text 属性,从而成功地在 xaml 中进行了验证。但是,我似乎无法在后面的代码中使用相同的代码。

  <TextBox.Text>
      <Binding Path="Text" UpdateSourceTrigger="PropertyChanged">
        <Binding.ValidationRules>
          <rules:IntegerValidationRule />
        </Binding.ValidationRules>
      </Binding>
    </TextBox.Text>

but when i try this in the code behind, it doesn't work.

但是当我在后面的代码中尝试这个时,它不起作用。

  Binding myBinding = new Binding();
  myBinding.Source = this;
  myBinding.Path = new PropertyPath("Text");
  myBinding.NotifyOnValidationError = true;
  myBinding.NotifyOnSourceUpdated = true;

  myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;

  myBinding.ValidationRules.Add(rule);
  MainTextBox.SetBinding(TextBlock.TextProperty, myBinding);

what am I missing?

我错过了什么?

采纳答案by James Joshua Street

Gave up on binding from code behind, i create a binding to a property in the xaml, and then in the constructor's code behind, I take the validation rule passed to the constructor and add it to the validation rules like so:

放弃了从后面的代码绑定,我在 xaml 中创建了一个属性的绑定,然后在后面的构造函数代码中,我将传递给构造函数的验证规则添加到验证规则中,如下所示:

public GenericDialogBox(string MainLabelContent, string WindowTitle, string TextboxDefaultText, ValidationRule rule)
    {
      this.DataContext = this;
      Text = "";
      if (rule != null)
      {
        TextBoxValidationRule = rule;
      }
      InitializeComponent();
      MainLabel.Content = MainLabelContent;
      Title = WindowTitle;

      Binding binding = BindingOperations.GetBinding(MainTextBox, TextBox.TextProperty);
      binding.ValidationRules.Add(rule);


      MainTextBox.SelectAll();
      MainTextBox.Focus();
    }

回答by Anatoliy Nikolaev

Try set for your Binding NotifyOnValidationErrorto True, by default it is False:

试试你的绑定设置NotifyOnValidationErrorTrue,默认情况下它是假:

Gets or sets a value that indicates whether the BindingValidationErrorevent is raised on validation errors.

获取或设置一个值,该值指示是否BindingValidationError在验证错误时引发事件。

Example:

例子:

<Binding NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged" ... />

Also you can see the ValidatesOnDataErrorsproperty, he is used when your ViewModelimplement the IDataErrorInfointerface.

您也可以看到ValidatesOnDataErrors属性,他在您ViewModel实现IDataErrorInfo接口时使用。