ComboBox SelectedValuePath验证不起作用

时间:2016-07-11 12:30:02

标签: c# wpf validation xaml combobox

我第一次尝试在XAML / WPF中实现数据验证。我已经阅读了几个教程,似乎有很多方法可以做到这一点。我已经确定了一种方法,但它无法正常工作。

首先,理想情况下我希望显示错误(上方 ComboBox以及Label右侧)。如果可能的话......

Location for validation error

我创建了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>

更新2

我可以看出屏幕上有一个验证符号。但它并没有减少组合的宽度,所以可以看出它。

2 个答案:

答案 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。