如果验证失败,请禁用 WPF 中的“保存”按钮
我采用了使用 IDataErrorInfo 接口和样式来验证 WPF 中文本框的标准方法,如下所示。 但是,当页面失效时,如何禁用“保存”按钮呢? 这是通过触发器以某种方式完成的吗?
Default Public ReadOnly Property Item(ByVal propertyName As String) As String Implements IDataErrorInfo.Item
Get
Dim valid As Boolean = True
If propertyName = "IncidentCategory" Then
valid = True
If Len(IncidentCategory) = 0 Then
valid = False
End If
If Not valid Then
Return "Incident category is required"
End If
End If
Return Nothing
End Get
End Property
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="3" />
<Setter Property="Height" Value="23" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<Border BorderBrush="Red" BorderThickness="1">
<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>
I've adopted what appears to be the standard way of validating textboxes in WPF using the IDataErrorInfo interface and styles as shown below. However, how can I disable the Save button when the page becomes invalid? Is this done somehow through triggers?
Default Public ReadOnly Property Item(ByVal propertyName As String) As String Implements IDataErrorInfo.Item
Get
Dim valid As Boolean = True
If propertyName = "IncidentCategory" Then
valid = True
If Len(IncidentCategory) = 0 Then
valid = False
End If
If Not valid Then
Return "Incident category is required"
End If
End If
Return Nothing
End Get
End Property
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="3" />
<Setter Property="Height" Value="23" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<Border BorderBrush="Red" BorderThickness="1">
<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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
有几点:
首先,我建议使用 RoutedCommand
ApplicationCommands.Save
来实现保存按钮的处理。如果您尚未查看 WPF 命令模型,可以获取独家新闻 这里。
现在,要实现该功能,您可以将命令绑定添加到 Window/UserControl 或 Button 本身:
在后面的代码中实现这些:
在
Save_CanExecute
中,设置e.CanExecute
基于文本框上绑定的有效性。如果您想使用 MVVM (Model-View-ViewModel) 设计模式来实现,请查看 Josh Smith 的帖子 CommandSinkBinding。
最后一点:如果您希望在
TextBox
中的值发生更改时立即更新启用/禁用,请在绑定上设置UpdateSourceTrigger="PropertyChanged"
文本框
。编辑:如果您想根据控件中的所有绑定进行验证/无效,这里有一些建议。
1) 您已经在实现
IDataErrorInfo
。 尝试实现IDataErrorInfo.Error
属性,使其返回对于您绑定到的所有属性都无效的字符串。 仅当您的整个控件绑定到单个数据对象时,这才有效。 Sete.CanExecute = string.IsNullOrEmpty(data.Error);
2) 使用反射获取相关控件上的所有公共静态 DependencyProperties。 然后在每个属性上循环调用
BindingOperations.GetBindingExpression(relevantControl, DependencyProperty)
以便您可以测试验证。3) 在构造函数中,手动创建嵌套控件上所有绑定属性的集合。 在 CanExecute 中,迭代此集合并使用
BindingOperation.GetBindingExpression()
获取表达式,然后检查来验证每个
。DependencyObject
/DepencyProperty
组合>BindingExpression.HasErrorA couple of things:
First, I would recommend using the RoutedCommand
ApplicationCommands.Save
for implementing the handling of the save button.If you haven't checked out the WPF Command model, you can get the scoop here.
Now, to implement the functionality, you can add a command binding to the Window/UserControl or to the Button itself:
Implement these in code behind:
In
Save_CanExecute
, sete.CanExecute
based on the validity of the binding on the text box.If you want to implement using the MVVM (Model-View-ViewModel) design pattern, check out Josh Smith's post on CommandSinkBinding.
One final note: If you want the enable/disable to be updated as soon as the value in the
TextBox
is changed, setUpdateSourceTrigger="PropertyChanged"
on the binding for theTextBox
.EDIT: If you want to validate/invalidate based on all of the bindings in the control, here are a few suggestions.
1) You are already implementing
IDataErrorInfo
. Try implementing theIDataErrorInfo.Error
property such that it returns the string that is invalid for all of the properties that you are binding to. This will only work if your whole control is binding to a single data object. Sete.CanExecute = string.IsNullOrEmpty(data.Error);
2) Use reflection to get all of the public static DependencyProperties on the relevant controls. Then call
BindingOperations.GetBindingExpression(relevantControl, DependencyProperty)
in a loop on each property so you can test the validation.3) In the constructor, manually create a collection of all bound properties on nested controls. In CanExecute, iterate through this collection and validate each
DependencyObject
/DepencyProperty
combination by usingBindingOperation.GetBindingExpression()
to get expressions and then examiningBindingExpression.HasError
.我为此创建了附加属性:
我在表单上像这样使用它:
I've created attached property just for this:
I'm using it like this on my forms: