向所有文本框添加自定义验证规则的简单方法

时间:2013-12-06 10:44:56

标签: c# wpf validationrules

我在设置页面中所有文本框的自定义验证规则时遇到问题。

我知道如何为1个单一文本框设置它:

<TextBox Margin="79,118,79,121" Name="textBox1" Style="{Binding EmptyTextboxValidator, UpdateSourceTrigger=PropertyChanged}">
    <TextBox.Text>
        <Binding Path="Text" UpdateSourceTrigger="PropertyChanged">
            <Binding.ValidationRules>
                <validators:StringRangeValidationRule MinimumLength="1" ErrorMessage="Text is te kort" />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

但是,如果我需要为每个单独的文本框添加此代码,我不确定这是否有用,因为它将是一个非常多的复制粘贴。必须有一个更简单的方法吗?

如果进行了大量搜索,但我找不到为所有文本框设置它的示例,只有示例为1个单一文本框设置它(如上所示)

这是文本框样式的代码:

<Application.Resources>
    <Style x:Key="EmptyTextboxValidator" TargetType="{x:Type TextBox}">
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <DockPanel LastChildFill="True">
                        <Border BorderBrush="Red" BorderThickness="3">
                            <AdornedElementPlaceholder Name="MyAdorner" />
                        </Border>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip" 
                        Value="{Binding RelativeSource={RelativeSource Self}, 
                        Path=(Validation.Errors)[0].ErrorContent}"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Application.Resources>

以及验证规则的代码:

using System;
using System.Windows.Controls;
using System.Globalization;

namespace MyValidators
{
    public class StringRangeValidationRule : ValidationRule
    {
        private int _minimumLength = 1;
        private string _errorMessage;

        public int MinimumLength
        {
            get { return _minimumLength; }
            set { _minimumLength = value; }
        }

        public string ErrorMessage
        {
            get { return _errorMessage; }
            set { _errorMessage = value; }
        }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            ValidationResult result = new ValidationResult(true, null);
            string inputString = (value ?? string.Empty).ToString();
            if (string.IsNullOrEmpty(inputString) || inputString.Length < MinimumLength)
            {
                result = new ValidationResult(false, this.ErrorMessage);
            }
            return result;
        }
    }
}

viewModel:

public class Data : INotifyPropertyChanged
{
    private int id = -1;
    private bool updated = true;
    private string text;
    private string name;

    public int ID
    {
        get
        {
            return id;
        }
        set
        {
            id = value;
            OnPropertyChanged("ID");
        }
    }

    public bool Updated
    {
        get
        {
            return updated;
        }
        set
        {
            updated = value;
        }
    }

    public string Text
    {
        get
        {
            return text;
        }
        set
        {
            text = value;
            OnPropertyChanged("Text");
        }
    }

    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
            OnPropertyChanged("Name");
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        updated = true;
    }
    #endregion
}

此外,我对xaml的了解有限,此代码是我为了更多地了解xaml而进行的测试的一部分。

也可能只有一种方法可以在文本框中添加字段,例如:

<TextBox ValidateStringLength="true"/>

甚至更好,如果我可以给它一个整数参数的字符串的最小长度:

<TextBox ValidateStringLength="5"/>

2中的任何一个(将其设置为我正在进行但是对于所有文本框一次)或上面演示的示例将非常感激。

1 个答案:

答案 0 :(得分:2)

该解决方案称为BindingGroup。看看这段代码:

<StackPanel Name="stackPanel1">
  <StackPanel.BindingGroup>
    <BindingGroup NotifyOnValidationError="True">
      <BindingGroup.ValidationRules>
        <src:ValidateDateAndPrice ValidationStep="ConvertedProposedValue" />
      </BindingGroup.ValidationRules>
    </BindingGroup>
  </StackPanel.BindingGroup>

  <HeaderedContentControl Header="Price">
    <TextBox Name="priceField"  Width="150">
      <TextBox.Text>
        <Binding Path="Price" Mode="TwoWay" />
      </TextBox.Text>
    </TextBox>
  </HeaderedContentControl>

  <HeaderedContentControl Header="Date Offer Ends">
    <TextBox Name="dateField" Width="150" >
      <TextBox.Text>
        <Binding Path="OfferExpires" StringFormat="d" />
      </TextBox.Text>
    </TextBox>
  </HeaderedContentControl>

  <StackPanel Orientation="Horizontal">
    <Button IsDefault="True" Click="Submit_Click">_Submit</Button>
    <Button IsCancel="True" Click="Cancel_Click">_Cancel</Button>
  </StackPanel>
</StackPanel>

所有TextBox都有ValidateDateAndPrice ValidationRule。

您还可以控制何时保存更改。

private void Submit_Click(object sender, RoutedEventArgs e)
{
    if (stackPanel1.BindingGroup.CommitEdit())
    {
        MessageBox.Show("Item submitted");
        stackPanel1.BindingGroup.SubmitEdit();
    }
}

在这种情况下,点击按钮时会提交更改。

修改

我发现你不知道你在做什么。

请在使用之前仔细阅读您想要使用的内容。

我将举例说明如何使其发挥作用。我用你的代码创建了这个例子。

<Window>
....
<Window.Resources>
    <Style TargetType="{x:Type TextBox}">
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <DockPanel LastChildFill="True">
                        <Border BorderBrush="Blue" BorderThickness="3">
                            <AdornedElementPlaceholder Name="MyAdorner" />
                        </Border>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip" 
                    Value="{Binding RelativeSource={RelativeSource Self}, 
                    Path=(Validation.Errors)[0].ErrorContent}"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<Window.BindingGroup>
    <BindingGroup>
        <BindingGroup.ValidationRules>
            <local:StringRangeValidationRule MinimumLength="5" ErrorMessage="Text too long!" />
        </BindingGroup.ValidationRules>
    </BindingGroup>
</Window.BindingGroup>

<Grid Margin="10" >
    <TextBox Margin="100, 5, 0, 0" HorizontalAlignment="Left" VerticalAlignment="Top"
             Text="{Binding Name}" Validation.ValidationAdornerSiteFor="{Binding ElementName=window}">
    </TextBox>
    <Button Content="Save" Click="Button_Click" Margin="0, 5, 100, 0" HorizontalAlignment="Right" VerticalAlignment="Top"/>
</Grid>

您需要在窗口中使用模板和样式才能使其正常工作。

这是背后的代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new Data() { Name = "Hello World!" };
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        window.BindingGroup.CommitEdit();
    }
}

public class Data : INotifyPropertyChanged
{
    private int id = -1;
    private bool updated = true;
    private string text;
    private string name;

    public int ID
    {
        get
        {
            return id;
        }
        set
        {
            id = value;
            OnPropertyChanged("ID");
        }
    }

    public bool Updated
    {
        get
        {
            return updated;
        }
        set
        {
            updated = value;
        }
    }

    public string Text
    {
        get
        {
            return text;
        }
        set
        {
            text = value;
            OnPropertyChanged("Text");
        }
    }

    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
            OnPropertyChanged("Name");
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        updated = true;
    }

    #endregion
}

public class StringRangeValidationRule : ValidationRule
{
    private int _minimumLength = 1;
    private string _errorMessage;

    public int MinimumLength
    {
        get { return _minimumLength; }
        set { _minimumLength = value; }
    }

    public string ErrorMessage
    {
        get { return _errorMessage; }
        set { _errorMessage = value; }
    }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        BindingGroup group = (BindingGroup)value;
        var item = group.Items[0];
        string inputString = (group.GetValue(item, "Name") ?? string.Empty).ToString();
        if (true || string.IsNullOrEmpty(inputString) || inputString.Length < MinimumLength)
        {
            return new ValidationResult(false, this.ErrorMessage);
        }

        return ValidationResult.ValidResult;
    }
}

如您所见,我更改了验证规则,并添加了Validation.ValidationAdornerSiteFor以指示TextBox应显示错误。

你应该能够复制过去,它会起作用。