C#wpf-如何在自定义控件中将文本框错误传递给父级
我尝试创建一个具有多级验证的文本框,因此如果有一些字段应该填写但不是必需的,请通知用户。我创建了一个控件,效果非常好,我只有一个问题。我想在其他用户控件中使用此新文本框。我有一个保存按钮,我想在这个文本框没有验证错误时启用这个按钮,但是验证错误似乎在我的自定义文本框控件中,所以这个按钮总是启用的。以下是控制xaml代码: MultiLevelValidationTextBox.xamlC#wpf-如何在自定义控件中将文本框错误传递给父级,c#,wpf,C#,Wpf,我尝试创建一个具有多级验证的文本框,因此如果有一些字段应该填写但不是必需的,请通知用户。我创建了一个控件,效果非常好,我只有一个问题。我想在其他用户控件中使用此新文本框。我有一个保存按钮,我想在这个文本框没有验证错误时启用这个按钮,但是验证错误似乎在我的自定义文本框控件中,所以这个按钮总是启用的。以下是控制xaml代码: MultiLevelValidationTextBox.xaml <Style x:Key="MultiLevelValidationTextBoxStyle" Tar
<Style x:Key="MultiLevelValidationTextBoxStyle" TargetType="local:MultiLevelValidationTextBoxControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MultiLevelValidationTextBoxControl">
<Grid>
<Grid.Resources>
<local:IsNullConverter x:Key="IsNullConverter" />
</Grid.Resources>
<TextBox
x:Name="PART_TextBox"
Text="{Binding Path=BindingText, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay}">
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Recommended, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True"/>
<Condition Binding="{Binding Path=BindingText, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource IsNullConverter}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="BorderBrush" Value="#fcba03" />
</MultiDataTrigger>
<DataTrigger Binding="{Binding Path=Required, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True">
<Setter Property="Text">
<Setter.Value>
<Binding Path="BindingText" RelativeSource="{RelativeSource Mode=TemplatedParent}" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<local:TextBoxTextValidation ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Polygon x:Name="PART_Polygon" Points="0,0 5,0 0,5 0,0" Margin="0,3,2,0" HorizontalAlignment="Right" FlowDirection="RightToLeft" ToolTip="A mező kitöltése ajánlott!">
<Polygon.Style>
<Style TargetType="Polygon">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Recommended, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True"/>
<Condition Binding="{Binding Path=BindingText, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource IsNullConverter}}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Fill" Value="#fcba03" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Recommended, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True"/>
<Condition Binding="{Binding Path=BindingText, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource IsNullConverter}}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Fill" Value="Transparent" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Recommended, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Fill" Value="Transparent" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Polygon.Style>
</Polygon>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我还有一个窗口,我想在这里使用它,如果需要texbox,有一个按钮应该被禁用:
<Button
Grid.Row="1"
Grid.Column="6"
Margin="10,0,0,0"
MinWidth="80"
Height="30">
那么,有没有办法将验证错误传递给父级?一切正常,只是这部分失灵
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=CustomTextBoxName, Path=(Validation.HasError), UpdateSourceTrigger=PropertyChanged}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
Save
</Button>
拯救
首先,您的代码太复杂,因此很难理解。您不必在文本框
的控制模板
内放置文本框
。那太荒谬了。如果您不知道控件的树是如何设计的,请始终查看并查找所需的控件。在你的情况下,这是最重要的。在这里,您可以了解到
文本框
的内容托管在滚动查看器
中,该查看器实际上是一个提供内容滚动的内容控件
:
这是文本框
的精简控制模板
(请访问上一链接查看完整代码):
验证失败时显示的控制模板
<ControlTemplate x:Key="ValidationErrorTemplate">
<DockPanel>
<TextBlock Text="!"
Foreground="#FCBA03"
FontSize="20" />
<Border BorderThickness="2"
BorderBrush="#FCBA03"
VerticalAlignment="Top">
<AdornedElementPlaceholder/>
</Border>
</DockPanel>
</ControlTemplate>
要将此TextBox
验证错误绑定到其他控件(如果使用绑定验证),只需执行以下操作:
<StackPanel>
<!-- Button will be disabled when the TextBox has validation errors -->
<Button Content="Press Me" Height="40">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ValidatedTextBox, Path=(Validation.HasError)}"
Value="True">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<TextBox x:Name="ValidatedTextBox"
Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}"
Style="{StaticResource TextBoxStyle}">
<TextBox.Text>
<Binding Path="BindingText"
RelativeSource="{RelativeSource TemplatedParent}"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:TextBoxTextValidation ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
这是一个有效的例子。您只需根据一些Required
属性添加条件验证即可对其进行扩展。只需将触发器添加到TextBoxStyle
。无需从TextBox
派生并创建自定义控件
评论
我强烈建议通过实现()在视图模型中实现数据验证。这增加了更多的灵活性和更简单的UI设计,因为绑定路径将被简化,UI膨胀将被删除。它还加强了封装(改进了设计),并支持对完整的验证逻辑进行单元测试。什么样的验证?乍一看你做错了什么。为什么您的文本框样式在其
ControlTemplate
中有一个TextBox
?你想做什么?@BionicCode我有一个表单,有很多字段、文本框、组合框等,我想标记必填字段和推荐字段。必填字段很容易,因为我可以使用验证。但是有些字段只是推荐的,但是用户不必填写。还有一个管理员,他可以设置哪些字段是必需的,哪些是推荐的。因此,我无法创建一些具有必需样式的字段,以及一些具有推荐样式的字段,因为管理员可以动态更改该字段是必需的、推荐的还是两者都没有。您如何知道哪些字段被管理员标记为必需的?是的,一定要进行VH ViewModel验证。更容易测试,更容易绑定,更容易禁用无效data@KrzysztofSkowronek是的,你说得对。我怎么会忘记提到遗嘱呢?非常感谢。
<TextBox Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}"
Style="{StaticResource TextBoxStyle}">
<TextBox.Text>
<Binding Path="BindingText"
RelativeSource="{RelativeSource TemplatedParent}"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:TextBoxTextValidation ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<ControlTemplate x:Key="ValidationErrorTemplate">
<DockPanel>
<TextBlock Text="!"
Foreground="#FCBA03"
FontSize="20" />
<Border BorderThickness="2"
BorderBrush="#FCBA03"
VerticalAlignment="Top">
<AdornedElementPlaceholder/>
</Border>
</DockPanel>
</ControlTemplate>
<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors)/ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
<StackPanel>
<!-- Button will be disabled when the TextBox has validation errors -->
<Button Content="Press Me" Height="40">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ValidatedTextBox, Path=(Validation.HasError)}"
Value="True">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<TextBox x:Name="ValidatedTextBox"
Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}"
Style="{StaticResource TextBoxStyle}">
<TextBox.Text>
<Binding Path="BindingText"
RelativeSource="{RelativeSource TemplatedParent}"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:TextBoxTextValidation ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>