首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果出现错误,阻止DataGridCell失去焦点,并在DataGridCell上获取错误模板?

如果出现错误,阻止DataGridCell失去焦点,并在DataGridCell上获取错误模板?
EN

Stack Overflow用户
提问于 2015-09-17 16:39:46
回答 1查看 1.7K关注 0票数 1

是否有可能在编辑模式下停止使用验证错误--由绑定对象的属性设置器中的异常引起--从失去焦点直到用户( a)纠正该错误,或者( b)通过按'Esc‘来恢复其更改?

此外,虽然我可以显示行的验证模板,但我似乎无法为DataGridCell本身触发它。

这是我们的测试风格。这很管用..。

代码语言:javascript
复制
<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>

这不是..。

代码语言:javascript
复制
<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>

以下是我们的专栏:

代码语言:javascript
复制
<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>
EN

回答 1

Stack Overflow用户

发布于 2015-09-18 08:26:02

  1. 是否可以在编辑模式下停止使用验证错误--由绑定对象的属性设置程序中的异常引起--从失去焦点直到用户( a)纠正该错误,或者( b)通过按'Esc'?来恢复其更改。

是的,这是可能的。例如,我们必须检查可以生成错误的HasErrors属性,并相应地设置其值。

这个答案使用了我在这里发布的解决方案中提出的概念:

WPF MVVM Validation DataGrid and disable CommandButton

DataGridCellTemplate xaml代码:

代码语言:javascript
复制
    <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

代码语言:javascript
复制
        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的ViewModel属性。

这些错误可以按这个顺序在三个层次上产生;

在更新值时由绑定引擎引发的异常,

b.在值到达ViewModel之前进行自定义验证。

c.在ViewModel中根据DataBase或其他东西进行验证。

当输入需要数字的字符时,通常会遇到这种情况。这是使用UpdateSourceExceptionFilter处理的。输出窗口显示如下所示:

代码语言:javascript
复制
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 :这是我们在TextBox中设置的。

代码语言:javascript
复制
      object ReturnExceptionHandler(object bindingExpression, Exception exception)
        {
            vm.HasErrors = true;

            return "This is from the UpdateSourceExceptionFilterCallBack.";
        }

这是我们用我们插入的验证规则来做的。但是我们的ViewModel将如何了解这些规则呢?我们将维护对这些规则的观察,并将事件处理程序附加到这些规则中,这样他们就可以通知他们的ViewModel,就像我们实现INotifyPropertyChanged通知绑定引擎一样。我们将规则添加到vm中,如下所示,MainWindow.cs

代码语言:javascript
复制
        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

代码语言:javascript
复制
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;
        }

在最后一级检查错误。我们处理集合中所有绑定对象的PropertyChanged事件。我们绑定到DataGrid的这个集合。

代码语言:javascript
复制
void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (((Class1)sender).ID > 7)
                HasErrors = true;
            else
                HasErrors = false;
        }

2.此外,虽然我可以显示行的验证模板,但我似乎无法为DataGridCell本身触发它。

DataGridRow有ValidationErrorTemplate,而DataGridCell没有。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32635618

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档