ContentControl中的GroupBox - 支持由绑定到ContentControl的内容实现的IDataErrorInfo

时间:2011-10-24 13:08:52

标签: c# .net wpf validation

我有一个ViewModel,它代表多个选项并实现IDataErrorInfo。此ViewModel仅在选择了至少其中一个选项时才有效。它绑定到ContentControlDataTemplate用于将ViewModel可视化为包含GroupBox的{​​{1}}。另一个ItemsControl将每个选项可视化为DataTemplate

我需要做什么,让CheckBoxContentControl一起工作,并在选中或取消选中复选框时检查有效性?


一些代码:

结合:

IDataErrorInfo

数据模板:

<ContentControl Content="{Binding GeneralInvoiceTypes, ValidatesOnDataErrors=True}"
                Margin="0,0,5,0" />

风格:

<DataTemplate DataType="{x:Type ViewModels:MultipleOptionsViewModel}">
  <GroupBox Header="{Binding Title}">
    <ItemsControl ItemsSource="{Binding Options}" />
  </GroupBox>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:OptionViewModel}">
  <CheckBox IsChecked="{Binding IsChecked}"
            Content="{Binding Name}"
            Margin="6,3,3,0" />
</DataTemplate>

3 个答案:

答案 0 :(得分:3)

  

要使ContentControl与之一起工作,我该怎么做   IDataErrorInfo并在选中复选框时检查其有效性   未检查?

Rachels 答案添加一点。

使用异步数据验证更容易解决此问题,但遗憾的是,WPF 4.5 is released之前无法使用此问题。

ContentGeneralInvoiceTypes中的MainViewModel绑定。由于我们无法进行异步数据验证,因此必须为PropertyChanged引发GeneralInvoiceTypes才能进行验证。这可行,但我会采用 Rachel 建议的方法,并在 MultipleOptionsViewModel

中引入另一个名为IsValid的属性

IsValid的绑定可以从Tag(或附加属性)到GeneralInvoiceTypes.IsValid完成。在任何IsChecked中更改Options时,我们还必须在 MultipleOptionsViewModel 中收到通知。这可以通过在CheckBoxes中使用命令绑定来完成。

因此需要对以下几行进行一些更改。

我还上传了一个示例项目,其实现方式如下: https://www.dropbox.com/s/fn8e4n4s68wj3vk/ContentControlValidationTest.zip?dl=0

ContentControl中

<ContentControl Content="{Binding Path=GeneralInvoiceTypes}"
                Tag="{Binding Path=GeneralInvoiceTypes.IsValid,
                              ValidatesOnDataErrors=True}" />

OptionViewModel DataTemplate

<DataTemplate DataType="{x:Type ViewModels:OptionViewModel}">
    <CheckBox IsChecked="{Binding IsChecked}"
                Content="{Binding Name}"
                Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContentControl}},
                                Path=DataContext.IsValidCheckCommand}"
                Margin="6,3,3,0" />
</DataTemplate>

MultipleOptionsViewModel

private ICommand m_isValidCheckCommand;
public ICommand IsValidCheckCommand
{
    get
    {
        return m_isValidCheckCommand ??
            (m_isValidCheckCommand = new RelayCommand(param => IsValidCheck()));
    }
}

private void IsValidCheck()
{
    IsValid = CheckIsValid();
}

private bool CheckIsValid()
{
    foreach (OptionViewModel option in Options)
    {
        if (option.IsChecked == true)
        {
            return true;
        }
    }
    return false;
}

private bool m_isValid;
public bool IsValid
{
    get { return m_isValid; }
    set
    {
        m_isValid = value;
        OnPropertyChanged("IsValid");
    }
}

public string this[string columnName]
{
    get
    {
        if (columnName == "IsValid")
        {
            if (IsValid == false)
            {
                return "At least 1 Option must be selected";
            }
        }
        return string.Empty;
    }
}

答案 1 :(得分:1)

包含GeneralInvoiceTypes属性的类是否实现IDataErrorInfo

设置ValidatesOnDataErrors=True将显示包含绑定属性的DataContext的验证错误,因此在这种情况下它是validing ParentViewModel.GetValidationError("GeneralInvoiceTypes"),而不是GeneralInvoiceTypes.GetValidationError()

在这种情况下,您可以将IDataErrorInfo添加到ParentViewModel并通过返回验证错误来验证GeneralInvoiceTypes属性,如下所示:

public string GetValidationError(string propertyName)
{
    if (propertyName == "GeneralInvoiceTypes")
        return GeneralInvoiceTypes.GetValidationError();

    return null;
}

或者您可以在IsValid上创建一个GeneralInvoiceTypes属性,该属性返回GetValidationError() == null并将验证触发器设置为{Binding IsValid},而不是Validation.HasError

答案 2 :(得分:0)

根据给出的答案,我解决了这个问题:

  1. 更改DataTemplate的{​​{1}},将MultipleOptionsViewModel属性与Options绑定:

    ValidatesOnDataErrors=True
  2. 将错误样式更改为定位<DataTemplate DataType="{x:Type ViewModels:MultipleOptionsViewModel}"> <GroupBox Header="{Binding Title}"> <ItemsControl ItemsSource="{Binding Options, ValidatesOnDataErrors=True}"/> </GroupBox> </DataTemplate> 而不是ItemsControl

  3. 当选中或取消选中其中一个子选项时,请确保ContentControlMultipleOptionsViewModel引发PropertyChanged
  4. 请确保"Options" MultipleOptionsViewModel在其实施中对IDataErrorInfo.Item的列"Options"作出反应,即在其索引器中。
  5. 此解决方案具有以下优点:它使用IDataErrorInfo的默认行为,即此ViewModel的使用者不需要任何特殊处理。

    我知道这个解决方案与我在问题中提到的问题不完全相同 - 错误模板现在显示在里面组合框而不是它周围,但这是我能活的东西用。