【问题标题】:ComboBox SelectedValuePath Validation not working组合框 SelectedValuePath 验证不起作用
【发布时间】:2016-07-11 12:30:02
【问题描述】:

我第一次尝试在 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 路径错误:在“对象”“OCLMEditorViewModel”(HashCode=17586541)上找不到“数字”属性。绑定表达式:路径=数字; DataItem='OCLMEditorViewModel' (HashCode=17586541);目标元素是 'ComboBox' (Name='');目标属性是“SelectedValuePath”(类型“字符串”)

我不明白为什么,因为我以前可以使用“数字”。

更新

如果值太高,我已扩展我的模型数据类以引发异常。例如:

[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。 在 OCLMEditor.Data.MeetingInfo.Meeting.set_BibleReadingMainStudyPoint(Int32 值) 在 D:\My Programs\OCLMEditor\OCLMEditor\Data\MeetingInfo\Meeting.cs:line 234 在 D:\My Programs\OCLMEditor\OCLMEditor\ViewModels\OCLMEditorViewModel.cs:line 184' 中的 OCLMEditor.OCLMEditorViewModel.set_SelectedStudentItem(学生值)处

我更改了 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

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

【问题讨论】:

  • 你能确认一下,你的OCLMEditorViewModel 有一个数字属性吗?
  • @lok​​usking 不,它没有。 Number 属性是 ComboBoxItem 对象的一部分。您可以在有效的代码中看到 SelectedValue/Path 是什么。
  • 你不能那样设置 SelectedValuePath 因为它是一个字符串。它存储用于从 SelectedItem 获取 SelectedValue 的路径
  • @CiccioRocca 如果我将SelectedValuePath 移回原来的位置,我该如何告诉它这样做Validation
  • @AndrewTruckle 您可以直接在组合框所选项目上进行操作。

标签: c# wpf validation xaml combobox


【解决方案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>

【讨论】:

  • 谢谢。出于某种原因,虽然这个 ValidationRule 似乎只在我关闭应用程序时触发(我让它进行手动源更新)。它应该在 SelectedValue 更改时进行验证。
  • @AndrewTruckle 当您将验证应用到SelectedValuePathSelectedValue 时是这种情况吗?
  • Meeting.BibleReadingMainStudyPoint 在我的代码中更改时,ComboValue 会被修改。由于该值为 25,因此我希望它能够得到验证并显示某种错误,而不仅仅是显示组合列表中的空选择。
  • @AndrewTruckle 当绑定的源值发生更改时,绑定调用 ValidationRules 对我来说有某种意义,但这似乎不是它的工作方式。无论如何,它也不会为我这样做。另一方面,您可能会争辩说,在 MVVM 术语中,视图模型应该负责确保它自己的状态是有效的,并且它不应该依赖视图来对其任何逻辑负责——尽管这当然意味着你在两个地方有相同的验证逻辑。
  • @AndrewTruckle ExceptionValidationRule 使用我添加到答案中的简单工具提示绑定为我工作。如果我是你,我会暂时注释掉你在组合框样式中的所有错误模板内容,看看它是否适用于默认内容和绑定到工具提示的简单错误内容,如我的示例中那样,然后一旦你已经开始工作了,我会问一个关于你的错误模板的新问题。从您最初关于绑定 SelectedValuePath 的问题开始,我们已经走了很长一段路。
【解决方案2】:

如果你想实现验证,你应该这样做:

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

【讨论】:

    猜你喜欢
    • 2016-10-06
    • 1970-01-01
    • 2020-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    相关资源
    最近更新 更多