我已经经历有关验证规则的一些帖子看了,但没有带碰到我遇到的问题。
我使用的是验证规则在WPF窗口一个文本框。 我有两个检查,一个空文本框,以及一个使用正则表达式匹配无效字符。
我的问题是这样的:
在我的文本框:
- A型 - 作品,显示空话
- 打退格为空字符串 - 作品,显示验证错误消息“请在所有字段中输入一个值”
- 类型! - 不工作 - 它应该显示“无效字符被发现”,但仍显示“请在所有字段中输入一个值。”
- Backspace键清空与字符串技术上的作品,因为它仍然显示第一个错误“请在所有字段中输入一个值。”
- A型 - 工程部,没有错误信息
- 类型! - 精细,显示信息“无效字符被发现。
同样的情况倒过来。
打开窗户
- 类型! - 精细,显示“无效字符被发现。
- Backspace键空字符串 - 仍显示“无效字符被发现”,而不是“请在所有字段中输入一个值。
我的代码如下:
ProviderNew.xaml:
<Label Name="lblProviderName" Content="Provider Name: "
Grid.Row="1" Grid.Column="0"/>
<TextBox Name="txtBoxProviderName" Margin="2"
MaxLength="20" CharacterCasing="Upper"
Grid.Row="1" Grid.Column="1" LostFocus="TxtBoxProviderNameLostFocus" TextChanged="TxtBoxProviderNameTextChanged">
<TextBox.Text>
<Binding ElementName="This" Path="ProviderName" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<Domain:ProviderValidation />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock x:Name="tbNameValidation" Foreground="Red" FontWeight="Bold" Margin="10,0,0,0"
Text="{Binding ElementName=txtBoxProviderName, Path=(Validation.Errors), Converter={StaticResource eToMConverter}}"
Grid.Row="1" Grid.Column="2" />
背后Privder码 - ProviderNew.xaml.cs
public static readonly DependencyProperty NewProviderNameProperty = DependencyProperty.Register("ProviderName",
typeof (string), typeof(ProviderNew), new UIPropertyMetadata(""));
public string ProviderName
{
get { return (string) GetValue(NewProviderNameProperty); }
set { SetValue(NewProviderNameProperty, value); }
}
值转换器类
public class ErrorsToMessageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var sb = new StringBuilder();
var errors = value as ReadOnlyCollection<ValidationError>;
if (errors != null && errors.Count > 0)
{
foreach (var e in errors.Where(e => e.ErrorContent != null))
{
sb.AppendLine(e.ErrorContent.ToString());
}
}
return sb.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Provider类
private string _providerName;
public string ProviderName
{
get { return _providerName; }
set
{
_providerName = value;
RaisePropertyChanged("ProviderName");
}
}
private void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
验证规则类
public class ProviderValidation : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
var str = value as string;
if (str != null && !Regex.IsMatch(str, @"^[a-zA-Z0-9]*$"))
{
return new ValidationResult(false, "Invalid characters were found.");
}
if (String.IsNullOrEmpty(str))
{
return new ValidationResult(false, "Please enter a value in all fields.");
}
return new ValidationResult(true, null);
}
}
我曾尝试是同时设置引发LostFocus和框TextChanged事件的使用给力更新:
var expression = txtBoxProviderName.GetBindingExpression(TextBox.TextProperty);
if (expression != null)
expression.UpdateSource();
在验证方法设置断点表明,正确的匹配完成并返回正确的ValidationResult,但它不能正常更新文本。
我做得令人难以置信的愚蠢?
任何建议将不胜感激。
编辑1。
是啊,我有工作,使用MultiDataTrigger并绑定到文本框。
什么不工作是当我第一次显示窗口,按钮被启用,这是我不希望它是,因为这可以让用户点击保存空文本框。
验证规则不直接从一开始的窗口打开时工作。
我设置文本框的焦点,如果它失去焦点或不正确的数据输入,然后验证规则踢和禁用按钮。
设置按钮默认禁用,使得它在打开禁用,但是当没有验证错误,它没有实现。
我可以把它通过强制验证规则的检查工作,对说Load事件,使用
var expression = txtBoxProviderName.GetBindingExpression(TextBox.TextProperty);
if (expression != null)
expression.UpdateSource();
但随后的窗口第一次打开时,它会立即显示验证错误消息,我真的不喜欢的样子“请在所有字段中输入一个值”。
任何办法解决这,或者我没有两全其美。
这里是按钮的代码
<Button x:Name="btnSave" Height="25" Width="100" Content="Save" HorizontalAlignment="Right" Margin="0,0,120,0"
Grid.Row="2" Click="BtnSaveClick" >
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=txtBoxProviderName, Path=(Validation.HasError)}" Value="False" />
<Condition Binding="{Binding ElementName=txtBoxHelpDesk, Path=(Validation.HasError)}" Value="False" />
<Condition Binding="{Binding ElementName=txtBoxRechargeInstructions, Path=(Validation.HasError)}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
谢谢,
奥尼尔
编辑2
一个快速的问题。 我找不到RelayCommand命名空间。 搜索其他代码周围,我发现从微软的MVVM的例子,实现RelayCommand:ICommand的类。
它是否正确?
该代码是:
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
/// <summary>
/// Creates a new command that can always execute.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
我实现我的ProviderNew.xaml.cs如下:
private ICommand saveCommand;
public ICommand SaveCommand
{
get
{
if (saveCommand == null)
{
saveCommand = new RelayCommand(p => DoSave(), p => CanSave() );
}
return saveCommand;
}
}
private bool CanSave()
{
if (!string.IsNullOrEmpty(ProviderName))
{
??? What goes here?
}
return true;
}
private bool DoSave()
{
// Save the information to DB
}
说实话,我不确定我应该在挡在了“如果(!string.IsNullOrEmpty(的ProviderName))”进行编码
另外你说要加在的DataContext ICommand的代码,所以不知道这是否是在正确的地方,因为当我打开窗户,保存为启用并单击它什么都不做,即使所有的领域有它的正确性。
下面是按钮的ProviderNew XAML代码
<Button x:Name="btnSave" Height="25" Width="100" Content="Save" HorizontalAlignment="Right" Margin="0,0,120,0"
Grid.Row="2" Command="{Binding SaveCommand}" >
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=txtBoxHelpDesk, Path=(Validation.HasError)}" Value="False" />
<Condition Binding="{Binding ElementName=txtBoxProviderName, Path=(Validation.HasError)}" Value="False" />
<Condition Binding="{Binding ElementName=txtBoxRechargeInstructions, Path=(Validation.HasError)}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
非常感激您的帮忙。
问候,
奥尼尔