c# - ContentControl 中的 GroupBox - 支持由绑定(bind)到 ContentControl 的内容实现的 IDataErrorInfo

标签 c# .net wpf validation

我有一个 ViewModel,它表示多个选项并实现 IDataErrorInfo。仅当至少选择了这些选项之一时,此 ViewModel 才有效。它绑定(bind)到 ContentControlDataTemplate 用于将 ViewModel 可视化为包含 ItemsControlGroupBox。另一个 DataTemplate 将每个选项可视化为一个 CheckBox

我必须做什么,才能使 ContentControlIDataErrorInfo 一起工作,并在选中或取消选中复选框时检查有效性?


部分代码:

绑定(bind):

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

风格:

<Style TargetType="{x:Type ContentControl}">
  <Style.Triggers>
    <Trigger Property="Validation.HasError"
             Value="true">
      <Setter Property="ToolTip"
              Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}" />
    </Trigger>
  </Style.Triggers>
  <Setter Property="Validation.ErrorTemplate">
    <Setter.Value>
      <ControlTemplate>
        <Grid>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="90*" />
            <ColumnDefinition Width="20" />
          </Grid.ColumnDefinitions>
          <Border BorderBrush="Red"
                  BorderThickness="1"
                  CornerRadius="2.75"
                  Grid.Column="0">
            <AdornedElementPlaceholder Grid.Column="0" />
          </Border>
          <TextBlock Foreground="Red"
                     Grid.Column="1"
                     Margin="0"
                     FontSize="12"
                     VerticalAlignment="Center"
                     HorizontalAlignment="Left"
                     x:Name="txtError">
            *
          </TextBlock>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

最佳答案

What do I have to do, to make the ContentControl work together with IDataErrorInfo and check the validity when a check box is checked or unchecked?

Rachels 回答添加一点。

使用异步数据验证可以更轻松地解决此问题,但不幸的是,在WPF 4.5 is released 之前不可用。 .

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

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

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

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

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

内容控件

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

OptionViewModel 数据模板

<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;
    }
}

关于c# - ContentControl 中的 GroupBox - 支持由绑定(bind)到 ContentControl 的内容实现的 IDataErrorInfo,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7876103/

相关文章:

WPF - 动画堆栈面板方向的变化?

c# - Automapper - 同时压平列表

c# - 管理托管 (C#) 和非托管 (C++) 对象的析构函数

.net - ASP.NET MVC 路由和文件路径

c# - 静态类和单例类设计模式有什么区别?

.net - 多文档应用程序的 MVVM 设计?

c# - WriteableBitmap 渲染带有文本修剪的文本 block

c# - 如何使用 dotnet(nuget 包)httpclient 配置 TCP 连接数?

c# - 限制进程的CPU使用率

c# - WPF ComboBoxItem Style 在 Combobox 获得焦点后加载