各位程序员大家好。我在使用IDataErrorInfo的Silverlight MVVM模式上遇到这个奇怪的问题。这是我在StackOverflow中提出的第一个问题,所以希望我能正确解释。这是交易:

我有一个巨大的Job Register ChildWindow,它具有一些控件,只有在选中名为HasPrevision的复选框时,才应启用这些控件。这个想法是:如果作业具有Prevision,则与该Prevision相关的所有控件都将被启用,否则,它们将被禁用。
现在,如果有一个预置,则用户必须在PrevisionType ComboBox中选择一个Prevision Type。因此,如果已选中HasPrevision复选框,则必须选择PrevisionType,但是如果未选中HasPrevision复选框,则可以不选择PrevisionType组合框。

这是这些控件的XAML(我不会在这里显示所有xaml,因为它很大,但是我相信只要显示这些行就可以解决问题):

<!-- The HasPrevision CheckBox -->
<CheckBox Grid.Column="1"
  Grid.Row="3"
  x:Name="cbxHasPrevision"
  IsChecked="{Binding SelectedJob.HasPrevision, Mode=TwoWay}"
  Margin="0,20,2,0" />

<!-- The PrevisionType ComboBox -->
<telerik:RadComboBox Grid.Column="1"
  Grid.Row="4"
  x:Name="cmbPrevisionType"
  IsEnabled="{Binding HasPrevision, Converter={StaticResource ControlesCadastroProcessoConverter}, ConverterParameter=IsEnabled}"
  ItemsSource="{Binding PrevisionTypeList, Mode=OneWay}"
  SelectedItem="{Binding SelectedJob.PrevisionType , Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True, ValidatesOnNotifyDataErrors=True}"
  Margin="0,4,48,4"
  Height="22"
  DisplayMemberPath="DsPrevisionType"/>

因此,如您所见,HasPrevision和PrevisionType属性绑定(bind)到我的ViewModel中的一个名为SelectedJob的属性。 SelectedJob是一个Job对象。我要做的就是使用作业类中的IDataErrorInfo接口(interface)来确定是否选择了PrevisionType。现在,如果HasPrevision属性为“true”,则仅需要PrevisionType,所以我的作业类具有IDataErrorInfo的以下代码:
public string this[string columnName]
    {
        get
        {
            switch (columnName)
            {
                case "PrevisionType":
                    if (HasPrevision && (PrevisionType== null))
                        return "Select a PrevisionType";
                    break;
            }
            return null;
        }

}

这对我来说听起来很合逻辑。当我调试代码时,它实际上是有效的:开关标识columnName,输入大小写“PrevisionType”,并且实际上在If语句内运行返回代码,返回错误消息,而不是默认的“return null”子句。但是错误消息没有显示错误!更糟糕的是:组合框不会自动验证事件。
单击“保存”按钮时,我检查是否有错误,并将PrevisionType组合框设置为InvalidFocused状态。 comboBox确实会在其周围显示红色边框,表明它处于错误状态,但错误消息为空白。当我将鼠标悬停在控件上时,将出现一个空的红色小框,上面没有任何内容。

甚至比这更奇怪:如果我从IF语句中删除“HasPrevision”检查,将代码保留如下,则会显示该消息并自动验证控件!
public string this[string columnName]
    {
        get
        {
            switch (columnName)
            {
                case "PrevisionType":
                    if (PrevisionType== null)
                        return "Select a PrevisionType";
                    break;
            }
            return null;
        }
    }

我能想到的是,由于我试图基于另一个属性值来验证一个属性,因此在set和get中间的某个位置,Silverlight环境变得“困惑”了吗?我不知道,我已经尝试了2天,但没有成功。
这是我认为相关的其他一些代码。

我的工作类别中的属性:
    private bool _HasPrevision;
    [DataMember]
    public bool HasPrevision
    {
        get { return _HasPrevision; }
        set
        {
            _HasPrevision= value;
            RaisePropertyChanged("HasPrevision");
        }
    }


    private PrevisionType.PrevisionType _PrevisionType { get; set; }
    [DataMember]
    public PrevisionType.PrevisionType PrevisionType
    {
        get { return _PrevisionType; }
        set
        {
            _PrevisionType = value;
            RaisePropertyChanged("PrevisionType");
        }
    }

我在ViewModel中的SelectedJob属性是:
public const string SelectedJobPropertyName = "SelectedJob";
    private Objects.Register.Job.Job _SelectedJob = null;
    public Objects.Register.Job.Job SelectedJob
    {
        get
        {
            return _SelectedJob;
        }

        set
        {
            if (_SelectedJob == value)
                return;

            var oldValue = _SelectedJob;
            _SelectedJob = value;
            RaisePropertyChanged(SelectedJobPropertyName , oldValue, value, true);
        }
    }

我的“保存”按钮代码为:
[...]

if(SelectedJob["PrevisionType"] != null)
{
    VisualStateManager.GoToState(cmbPrevisionTypeControl, "InvalidFocused", true);
    return;
}

[...]

在此先感谢您,如果我对此解释有些困惑,我们深表歉意。

编辑1:我已经在这里阅读过这些问题,但是它们并不能完全帮助我:

IDataErrorInfo - not seeing any error message even though one gets picked up

Silverlight IDataErrorInfo message does not show in custom control's textbox

最佳答案

我以类似的方式使用Telerik RadComboBox,并且在显示错误消息时没有任何问题。这是我的XAML供您引用,希望对您有所帮助...

 <TextBlock Text="Select a User to Assign the Current Step To:" Grid.Row="3" Visibility="{Binding ShowAssigneeUser}"/>
            <telerik:RadComboBox x:Name="cmbAllActiveCrmUsers"
                                 IsEditable="True"
                                 Grid.Row="4"
                                 telerik:TextSearch.TextPath="FullName"
                                 Text="{Binding FullName, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
                                 VerticalAlignment="Center"
                                 Visibility="{Binding ShowAssigneeUser}"
                                 ItemsSource="{Binding AllActiveCrmUsersExceptCurrentUser}"
                                 SelectedIndex="{Binding DefaultAssigneeUserIndex, Mode=TwoWay}"
                                 ItemTemplate="{StaticResource ComboBoxMultilineTemplate}"
                                 Style="{StaticResource ComboBoxStyle}"
                                 Command="{Binding AssignUserChangeCommand}"
                                 CommandParameter="{Binding SelectedIndex, ElementName=cmbAllActiveCrmUsers}"
                                  >
                <telerik:RadComboBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel />
                    </ItemsPanelTemplate>
                </telerik:RadComboBox.ItemsPanel>
            </telerik:RadComboBox>

09-25 22:30