我第一次尝试在XAML / WPF中实现数据验证。我已经阅读了几个教程,似乎有很多方法可以做到这一点。我已经确定了一种方法,但它无法正常工作。
首先,理想情况下我希望显示错误(上方 ComboBox
以及Label
的右侧)。如果可能的话......
我创建了ValidationRule
:
using System;
using System.Globalization;
using System.Windows.Controls;
namespace OCLMEditor.ValidationRules
{
class StudyPointValidationRule : ValidationRule
{
public bool BibleReading { get; set; }
public StudyPointValidationRule()
{
BibleReading = false;
}
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if(value == null)
return new ValidationResult(false, "The study point has not been set.");
int iStudy = (int)value;
if(BibleReading)
{
if(iStudy > 17)
return new ValidationResult(false, "Maximum study point for bible readings is 17.");
}
else
{
if(iStudy == 7 || iStudy > 51)
return new ValidationResult(false, "Study points 7, 52 and 53 are not permitted for student items.");
}
return new ValidationResult(true, null);
}
}
}
然后,我将其添加到XAML中的Window
类:
xmlns:ValidationRules="clr-namespace:OCLMEditor.ValidationRules":
在Window.Resources
:
<ControlTemplate x:Key="StudyPointValidationTemplate">
<DockPanel>
<TextBlock Foreground="Red" FontSize="20">!</TextBlock>
<AdornedElementPlaceholder/>
</DockPanel>
</ControlTemplate>
然后,对于我想要应用此验证的第一个ComboBox,我将其更改为:
<ComboBox DataContext="{Binding DataContext, ElementName=oclmEditor}"
ItemsSource="{Binding ReadingStudyPointsList}"
ItemContainerStyle="{StaticResource StudyPointComboBoxStyle}"
ItemTemplate="{StaticResource StudyPointComboItem}"
Validation.ErrorTemplate="{StaticResource StudyPointValidationTemplate}"
Tag="{Binding Meeting.BibleReadingMainName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding Meeting.BibleReadingMainStudyPoint, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="Number"/>
要:
<ComboBox DataContext="{Binding DataContext, ElementName=oclmEditor}"
ItemsSource="{Binding ReadingStudyPointsList}"
ItemContainerStyle="{StaticResource StudyPointComboBoxStyle}"
ItemTemplate="{StaticResource StudyPointComboItem}"
Validation.ErrorTemplate="{StaticResource StudyPointValidationTemplate}"
Tag="{Binding Meeting.BibleReadingMainName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding Meeting.BibleReadingMainStudyPoint, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
>
<ComboBox.SelectedValuePath>
<Binding Path="Number">
<Binding.ValidationRules>
<ValidationRules:StudyPointValidationRule BibleReading="True"/>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedValuePath>
</ComboBox>
我收到此错误:
System.Windows.Data错误:40:BindingExpression路径错误:&#39; Number&#39;在&#39; object&#39;上找不到的属性&#39;&#39; OCLMEditorViewModel&#39; (的HashCode = 17586541)&#39 ;. BindingExpression:路径=号码;的DataItem =&#39; OCLMEditorViewModel&#39; (的HashCode = 17586541);目标元素是&#39; ComboBox&#39; (名称=&#39;&#39); target属性是&#39; SelectedValuePath&#39; (键入&#39; String&#39;)
我不明白为什么,因为我能够使用&#34; Number&#34;先前。
如果值太高,我扩展了我的Model Data类以抛出异常。例如:
[XmlIgnore]
public int BibleReadingMainStudyPoint
{
get { return _TFGW.BibleReadingItem.Main.StudyPoint; }
set
{
if (value > 17)
throw new ArgumentOutOfRangeException("Maximum Bible reading study point is 17.");
_TFGW.BibleReadingItem.Main.StudyPoint = value;
MarkDirty();
OnPropertyChanged("BibleReadingMainStudyPoint");
}
}
我肯定会抛出异常:
参数名称:最大圣经阅读学习点数为17。 位于D:\ My Programs \ OCLMEditor \ OCLMEditor \ Data \ MeetingInfo \ Meeting.cs中的OCLMEditor.Data.MeetingInfo.Meeting.set_BibleReadingMainStudyPoint(Int32值):第234行 位于D:\ My Programs \ OCLMEditor \ OCLMEditor \ ViewModels \ OCLMEditorViewModel.cs中的OCLMEditor.OCLMEditorViewModel.set_SelectedStudentItem(学生值):第184行&#39;
我更改了XAMl,因为ValidationRule不适用于此实例:
<Binding.ValidationRules>
<ExceptionValidationRule/>
</Binding.ValidationRules>
所以我期待它现在可以直观地显示错误。屏幕上没有任何内容。
资源:
<Window.Resources>
<ValueConverters:StudyPointWorkingOn x:Key="StudyPointWorkingOn" />
<Style x:Key="StudyPointComboBoxStyle" TargetType="ComboBoxItem">
<Setter Property="Tag" Value="{Binding Number}" />
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource StudyPointWorkingOn}">
<Binding RelativeSource="{RelativeSource Self}" Path="Tag"/>
<Binding Path="DataContext" ElementName="oclmEditor" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="Tag" RelativeSource="{RelativeSource AncestorType=ComboBox}"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="StudyPointComboItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number}"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding Title}"/>
</StackPanel>
</DataTemplate>
<ControlTemplate x:Key="StudyPointValidationTemplate">
<DockPanel>
<TextBlock Foreground="Red" FontSize="20">!</TextBlock>
<AdornedElementPlaceholder/>
</DockPanel>
</ControlTemplate>
</Window.Resources>
我可以看出屏幕上有一个验证符号。但它并没有减少组合的宽度,所以可以看出它。
答案 0 :(得分:1)
SelectedValuePath
is a string。它告诉ComboBox
所选数据项的哪个值要分配给SelectedValue
属性。没有什么可以验证的;那不是告诉你用户选择的属性。选择更改时不应更改,因为Number
始终是您要用于SelectedValue
的属性(除非您更改ComboBox
中项目的类型 - 但这是不是你在做什么)。
要与验证绑定的属性为SelectedValue
,您在问题中将其作为属性获取。
<ComboBox
...other properties...
SelectedValuePath="Number"
>
<ComboBox.SelectedValue>
<Binding
Path="Meeting.BibleReadingMainStudyPoint"
Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged"
>
<Binding.ValidationRules>
<ValidationRules:StudyPointValidationRule BibleReading="True"/>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedValue>
<ComboBox.Style>
<Style
TargetType="ComboBox"
BasedOn="{StaticResource {x:Type ComboBox}}"
>
<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>
</ComboBox.Style>
</ComboBox>
答案 1 :(得分:1)
如果你想要进行验证,你应该做这样的事情:
<ComboBox SelectedValuePath="Number" DataContext="{Binding DataContext, ElementName=oclmEditor}"
ItemsSource="{Binding ReadingStudyPointsList}"
ItemContainerStyle="{StaticResource StudyPointComboBoxStyle}"
ItemTemplate="{StaticResource StudyPointComboItem}"
Validation.ErrorTemplate="{StaticResource StudyPointValidationTemplate}"
Tag="{Binding Meeting.BibleReadingMainName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding Meeting.BibleReadingMainStudyPoint, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
>
<ComboBox.SelectedValue>
<Binding Path="Meeting.BibleReadingMainName" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<ValidationRules:StudyPointValidationRule BibleReading="True"/>
</Binding.ValidationRules>
</Binding>
</ComboBox.SelectedValue>
</ComboBox>
使用SelectedValuePath只是告诉使用哪个属性从SelectedItem获取SelectedValue。