0

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

我知道如何为 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;
        }
    }
}

视图模型:

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"/>

两者中的任何一个(按照我正在做的方式设置,但同时针对所有文本框)或我上面演示的示例将不胜感激。

4

1 回答 1

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>

所有的文本框都有 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>
</Window>

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

这是后面的代码:

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 应显示错误。

您应该能够复制和粘贴它,它会起作用。

于 2013-12-06T11:14:27.683 回答