如果有错误,阻止DataGridCell失去焦点,并在DataGridCell上获取错误模板
本文关键字:DataGridCell 取错误 获取 焦点 有错误 阻止 失去 如果 并在 | 更新日期: 2023-09-27 18:13:22
是否有可能阻止DataGridCell
在编辑模式下出现验证错误-由绑定对象的属性设置器中的异常引起-从失去焦点直到用户a)纠正该错误,或b)通过按下'Esc'恢复其更改?
另外,虽然我可以为行显示验证模板,但我似乎无法让它为DataGridCell本身触发。
这是我们的测试样式。这工作…
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
这并不…
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="Background" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
我们的专栏如下:
<DataGrid.Columns>
<DataGridTextColumn x:Name="NameColumn"
Header="Name"
Binding="{Binding Name, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}"
Width="*" />
<DataGridTextColumn x:Name="ValueColumn"
Header="Value"
Binding="{Binding Value, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}"
Width="*" />
</DataGrid.Columns>
- 是否有可能在编辑模式下停止DataGridCell的验证错误-由绑定对象的属性设置器中的异常引起-从失去焦点直到用户a)纠正该错误,或b)通过按"Esc"恢复其更改?
是的,有可能。例如,我们必须检查ViewModel的HasErrors属性,其中可以生成错误,并相应地设置其值。
这个答案使用了我在这里发布的一个解决方案中提出的概念:
WPF MVVM Validation DataGrid和disable CommandButton
DataGridCellTemplate xaml code:
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox VerticalAlignment="Stretch" VerticalContentAlignment="Center" Loaded="TextBox_Loaded" PreviewLostKeyboardFocus="TextBox_PreviewLostKeyboardFocus" PreviewKeyUp="TextBox_PreviewKeyUp">
<TextBox.Triggers>
</TextBox.Triggers>
<TextBox.Text>
<Binding Path="ID" UpdateSourceExceptionFilter="ReturnExceptionHandler" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True" ValidatesOnExceptions="True" >
<Binding.ValidationRules>
<v:CustomValidRule ValidationStep="ConvertedProposedValue"></v:CustomValidRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
MainWindow.cs
ViewModel vm = new ViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = vm;
}
// This is wrong and will result in StackOverflow exception
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (vm.HasErrors)
{
TextBox b = (TextBox)sender;
b.Focus();
}
}
private void TextBox_PreviewLostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
TextBox b = (TextBox)sender;
if (vm.HasErrors)
{
e.Handled = true;
b.Focus();
b.CaptureMouse();
}
else {
e.Handled = false;
b.ReleaseMouseCapture();
}
}
private void TextBox_PreviewKeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Escape)
{
TextBox b = (TextBox)sender;
b.Undo();
}
}
现在,我们需要检查错误并在这些地方设置ViewModel的HasErrors属性。
按此顺序可产生3个级别的错误:
。绑定引擎在更新值
时抛出的异常。b。在值到达ViewModel之前自定义验证。
c。在ViewModel中对DataBase或其他东西进行验证。
。当在需要数字的地方输入字符时,通常会遇到这种情况。这是使用UpdateSourceExceptionFilter处理的。输出窗口显示如下:
System.Windows.Data Error: 7 : ConvertBack cannot convert value 'a' (type 'String'). BindingExpression:Path=ID; DataItem='Class1' (HashCode=66068479); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') FormatException:'System.FormatException: Input string was not in a correct format.
at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
我们的UpdateSourceExceptionFilterCallback:这是我们在上面的文本框中设置的。
object ReturnExceptionHandler(object bindingExpression, Exception exception)
{
vm.HasErrors = true;
return "This is from the UpdateSourceExceptionFilterCallBack.";
}
b。这是通过我们插入的验证规则来实现的。但是我们的ViewModel如何知道这些规则呢?我们将维护这些规则的一个可观察集合,并将事件处理程序附加到这些规则上,这样它们就可以通知它们的ViewModel,就像我们实现INotifyPropertyChanged来通知绑定引擎一样。我们像这样将规则添加到vm中,MainWindow.cs
private void TextBox_Loaded(object sender, RoutedEventArgs e)
{
Collection<ValidationRule> rules= ((TextBox)sender).GetBindingExpression(TextBox.TextProperty).ParentBinding.ValidationRules;
foreach (ValidationRule rule in rules)
vm.Rules.Add(rule);
}
ViewModel.cs
void Rules_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
foreach (var v in e.NewItems)
((IViewModelUIRule)v).ValidationDone += ViewModel_ValidationDone;
}
void ViewModel_ValidationDone(object sender, ViewModelUIValidationEventArgs e)
{
HasErrors = e.IsValid;
}
c。在最后一级进行错误检查。我们处理集合中所有绑定对象的PropertyChanged事件。我们将这个集合绑定到DataGrid。
void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (((Class1)sender).ID > 7)
HasErrors = true;
else
HasErrors = false;
}
2。此外,虽然我可以为行显示验证模板,但我似乎无法让它为DataGridCell本身触发。
datagdrow有ValidationErrorTemplate,而DataGridCell没有。