C# WPF验证取决于必填/非必填字段
我是WPF开发的新手,但我正在考虑如何一石三鸟。 示例:我有一个包含2个文本框和2个文本块的表单。 第一个“bird”是,如果某些文本块引用必填字段,则可以使用星号“充实”它们:C# WPF验证取决于必填/非必填字段,c#,wpf,validation,xaml,C#,Wpf,Validation,Xaml,我是WPF开发的新手,但我正在考虑如何一石三鸟。 示例:我有一个包含2个文本框和2个文本块的表单。 第一个“bird”是,如果某些文本块引用必填字段,则可以使用星号“充实”它们: 第一点:您可以为控件定义自定义模板,在其中添加所需的可视元素(星号等)。可以使用触发器控制其可见性。(关于这方面的更多细节,您可以单独提问) Second/Third:您可以在AgeController上定义布尔属性IsRequired,并在定义验证时将其设置为TRUE/FALSE: <TextBox.Text
第一点:您可以为控件定义自定义模板,在其中添加所需的可视元素(星号等)。可以使用触发器控制其可见性。(关于这方面的更多细节,您可以单独提问)
Second/Third:您可以在AgeController
上定义布尔属性IsRequired
,并在定义验证时将其设置为TRUE/FALSE:
<TextBox.Text>
<Binding Path="blabla" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<local:AgeController ValidationStep="RawProposedValue"
IsRequired="**True**" />
OR: IsRequired="**False**" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
1。TextBlock没有ControlTemplate属性。因此,所需的(*)不能添加到文本块中
<local:LabelWithRequiredInfo Content="_Firstname"
Target="{Binding ElementName=textboxFirstname, Mode=OneWay}"
... />
Label有一个controltemplate,可以为输入字段提供焦点。让我们使用它
按下Alt+F时,使用Target属性将焦点传递给文本框:
<!-- Prefixing Firstname with _ allows the user to give focus
to the textbox (Target) by pressing Alt + F-->
<local:LabelWithRequiredInfo Content="_Firstname"
IsRequired="false"
Target="{Binding ElementName=textboxFirstname,
Mode=OneWay}" ... />
3。让我们用Themes\Generic.xaml中的RequiredInfo模板填充Label
<local:LabelWithRequiredInfo Content="_Firstname"
Target="{Binding ElementName=textboxFirstname, Mode=OneWay}"
... />
(但是模板首先是在MainWindow.xaml right中设计的,单击标签/编辑模板/复制-因此可以可视化-然后模板内容在Generic.xaml中复制)
6。并在您找到的绑定中使用它:
<TextBox x:Name="textboxFirstname" HorizontalAlignment="Left" Height="23" Margin="236,94,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120">
<TextBox.Text>
<Binding Path="Firstname" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<local:RequiredValidationRule IsRequired="true" ValidationStep="RawProposedValue" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
您将在此处找到完整的解决方案:
对于可重用性和您描述需求的方式,可能需要一个聚合控件。我认为UserControl+一些DependencyProperty是一个完美的选择
对于我的UserControl,我希望
<UserControl x:Class="WpfApplication1.InputFieldControl"
x:Name="InputUserCtrl"
... >
<StackPanel x:Name="MainPanel">
<TextBlock x:Name="Label">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}{1}:">
<Binding Path="InputLabel" ElementName="InputUserCtrl"/>
<Binding Path="RequiredStringSymbol" ElementName="InputUserCtrl"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<TextBox x:Name="Value" Text="{Binding DataContext, ElementName=InputUserCtrl}"/>
</StackPanel>
我可以像这样使用控件:
<StackPanel>
<customCtrl:InputFieldControl Required="True"
RequiredStringSymbol="+"
InputLabel="RequiredField"/>
<customCtrl:InputFieldControl Required="False"
InputLabel="NormalField"/>
<customCtrl:InputFieldControl Required="True"
RequiredStringSymbol="*"
InputLabel="AnotherRequiredField">
</customCtrl:InputFieldControl>
</StackPanel>
至于验证部分,我宁愿使用IDataErrorInfo。这可以与您的ViewModel一起使用,因为我们现在可以绑定所需的属性。这里是第二个答案,它并不完全是Massimo的问题
我这样做了,因为我认为对于XAML设计器来说,它可能更容易使用
目标是使标签(子类实际上具有所需的红色符号(*))更易于使用
由于通常的目标属性
<local:LabelWithRequiredInfo Content="_Firstname"
Target="{Binding ElementName=textboxFirstname, Mode=OneWay}"
... />
因此,LabelWithRequiredInfo的模板可以使用它来显示一些文本:
<local:LabelWithRequiredInfo RequiredLegend="(*)" ... />
或者更像XAML的东西:
<local:LabelWithRequiredInfo ... >
<local:LabelWithRequiredInfo.RequiredLegend>
<TextBlock Text="(*)" Foreground="Red" />
</local:LabelWithRequiredInfo.RequiredLegend>
只需在themes\Generic.xaml中更改控件模板
它现在使用ContentControl显示文本或控件:
<Style TargetType="{x:Type local:LabelWithRequiredInfo}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:LabelWithRequiredInfo}">
<Border ...>
<Grid>
<Grid.ColumnDefinitions ... />
<ContentPresenter ... />
**<ContentControl Content="{TemplateBinding RequiredLegend}" Visibility="{TemplateBinding IsRequired,Converter={StaticResource booleanToVisibilityConverter}}" Grid.Column="1" /> **
</Grid>
** **
以下是完整工作解决方案的链接:
最佳编码@Massimo,我是否很好地理解了必选和必选之间的区别?如我所示,强制可以吗。。。因为我不太清楚什么是非法字符。Regardsorry@Emmanuel,我指的是“不需要”。不知怎的,在我的脑海里,我认为强制性意味着另一件事。。。我还有其他工作要做,所以我无法查看您的回复(抱歉@all)。我是崔恩来确认并把赏金给合适的人!同时,我要感谢大家的努力:)事实上,对我来说(从我在英语词典中看到的),manadatory=required是的,但当我写这个问题时,我真的认为强制性与强制性相反。我现在正在解决这个问题。对每个人来说:我只是做了一个编辑来展示如何使用目标按钮。谢谢你的投票,我刚刚得到了10票的“好答案解决方案”
public partial class InputFieldControl : UserControl
{
// Required property
public static readonly DependencyProperty RequiredProperty =
DependencyProperty.Register("Required",
typeof(bool), typeof(InputFieldControl),
new PropertyMetadata(true, OnRequiredChanged));
private static void OnRequiredChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){
InputFieldControl ctrl = d as InputFieldControl;
// symbol is voided
if ((bool)e.NewValue == false)
ctrl.RequiredStringSymbol = string.Empty;
}
public bool Required {
get { return (bool)GetValue(RequiredProperty); }
set { SetValue(RequiredProperty, value); }
}
// Required string symbol
public static readonly DependencyProperty RequiredStringSymbolProperty =
DependencyProperty.Register("RequiredStringSymbol",
typeof(string), typeof(InputFieldControl),
new PropertyMetadata("*"));
public string RequiredStringSymbol{
get { return (string)GetValue(RequiredStringSymbolProperty); }
set { SetValue(RequiredStringSymbolProperty, value); }
}
// Input Label
public static readonly DependencyProperty InputLabelProperty =
DependencyProperty.Register("InputLabel",
typeof(string), typeof(InputFieldControl),
new PropertyMetadata(string.Empty));
public string InputLabel{
get { return (string)GetValue(InputLabelProperty); }
set { SetValue(InputLabelProperty, value); }
}
<StackPanel>
<customCtrl:InputFieldControl Required="True"
RequiredStringSymbol="+"
InputLabel="RequiredField"/>
<customCtrl:InputFieldControl Required="False"
InputLabel="NormalField"/>
<customCtrl:InputFieldControl Required="True"
RequiredStringSymbol="*"
InputLabel="AnotherRequiredField">
</customCtrl:InputFieldControl>
</StackPanel>
<local:LabelWithRequiredInfo Content="_Firstname"
Target="{Binding ElementName=textboxFirstname, Mode=OneWay}"
... />
public LabelWithRequiredInfo()
{
var dpd = DependencyPropertyDescriptor.FromProperty(Label.TargetProperty, typeof(Label));
dpd.AddValueChanged(this, SearchForRequiredValidationRule);
}
private void SearchForRequiredValidationRule(object sender, EventArgs e)
{
var textbox = Target as TextBox;
if (textbox != null)
{
Binding binding = BindingOperations.GetBinding(textbox, TextBox.TextProperty);
var requiredValidationRule = binding.ValidationRules
.OfType<RequiredValidationRule>()
.FirstOrDefault();
if (requiredValidationRule != null)
{
// makes the required legend (red (*) for instance) to appear
IsRequired = true;
}
}
}
<local:LabelWithRequiredInfo Content="_I agree with the terms of contract"
Target="{Binding ElementName=checkboxIAgree}"
IsRequired='"true"
... />
public Object RequiredLegend
{
get { return (Object)GetValue(RequiredLegendProperty); }
set { SetValue(RequiredLegendProperty, value); }
}
// Using a DependencyProperty as the backing store for RequiredLegend. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RequiredLegendProperty =
DependencyProperty.Register("RequiredLegend", typeof(Object), typeof(LabelWithRequiredInfo), new PropertyMetadata(null));
<local:LabelWithRequiredInfo RequiredLegend="(*)" ... />
<local:LabelWithRequiredInfo ... >
<local:LabelWithRequiredInfo.RequiredLegend>
<TextBlock Text="(*)" Foreground="Red" />
</local:LabelWithRequiredInfo.RequiredLegend>
<Style TargetType="{x:Type local:LabelWithRequiredInfo}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:LabelWithRequiredInfo}">
<Border ...>
<Grid>
<Grid.ColumnDefinitions ... />
<ContentPresenter ... />
**<ContentControl Content="{TemplateBinding RequiredLegend}" Visibility="{TemplateBinding IsRequired,Converter={StaticResource booleanToVisibilityConverter}}" Grid.Column="1" /> **
</Grid>